понедельник, 7 февраля 2011 г.

_GetPerformanceCounter()

Синтаксис:
_GetPerformanceCounter()
Назначение:
Возвращает число миллисекунд (1000-чных долей секунды) прошедших с момента включения компьютера.
Замечание:
Разница между значениями двух замеров позволяет определить количество миллисекунд прошедших между замерами.



1С:Предприятие 7.7
Следующее тестирование, наглядно показывает как использование функции Сообщить() грузит процесс выполнения алгоритма. Итак, код:


Процедура Сформировать()
   
тайм = _GetPerformanceCounter();
    Сообщить(
тайм);
   
тайм2 = _GetPerformanceCounter();
   
икс = 0;
    Пока
тайм2 - тайм < 2000 Цикл
       
икс = икс + 1;
        Сообщить(
тайм2);
       
тайм2 = _GetPerformanceCounter();
    КонецЦикла;
    Сообщить(
"Значение икс: " + икс);
КонецПроцедуры
//Сформировать


Возвращает "Значение икс: 518", "Значение икс: 511", "Значение икс: 513" и т.д (в среднем икс наращивается до 514. Далее, код:


Процедура Сформировать()
   
тайм = _GetPerformanceCounter();
    Сообщить(
тайм);
   
тайм2 = _GetPerformanceCounter();
   
икс = 0;
    Пока
тайм2 - тайм < 2000 Цикл
       
икс = икс + 1;
       
//Сообщить(тайм2);
       
тайм2 = _GetPerformanceCounter();
    КонецЦикла;
    Сообщить(
"Значение икс: " + икс);
КонецПроцедуры
//Сформировать


Возвращает "Значение икс: 292152", "Значение икс: 291755", "Значение икс: 292463"
И еще один эксперимент, //Сообщить(тайм2); меняем на Состояние(тайм2); результат: "Значение икс: 67404", "Значение икс: 67843", "Значение икс: 66169".
Все тесты проходили один за другим в порядке, как написаны выше, в одно и то же время, на одной машине, приблизительно одинаково загруженную процессами (изменялись только треки в foobar2000)
Но! На самом деле всё вышесказанное не было основной темой для написания этого поста.


 Основная тема: _GetPerformanceCounter() в 1С 8
Но прежде чем перейти к восьмерке, вот что еще интересно:
_GetPerformanceCounter() возвращает unsigned long и соответственно обнуляется каждые 49,7 дней ( unsigned long от 0 до 4294967295, соответственно 4294967295/1000/60/60/24 = 49,7)


1С:Предприятие 8.1.15.14
Сегодня для меня было новостью, что _GetPerformanceCounter() отсутствует в 8.1 и использование её не предусмотрено. Возможно есть альтернативы о которых я на данный момент не знаю, но всё же интересующихся судьбой ГПК() в восьмерке людей я нашел. И вот какие "аналоги" были предложены:

1. ссылаются на автора Gloom и ссылку(к сожалению не работающую) http://1c.realnet.ru/kuban/138828.html код:
scrptCtrl=createobject("MSScriptControl.ScriptControl");
scrptCtrl.language="jscript";
scrptCtrl.addcode("
  |function GetMilliseconds()
  |{
  |d = new Date();
 |return(d.getHours()*3600000+d.getMinutes()*60000+d.getSeconds()*1000+d.getMilliseconds());
  |}
  |"
);
Сообщить(scrptCtrl.run("GetMilliseconds"));

похоже на правду, но результат _GetPerformanceCounter() дал мне в 7.7: 4845063, а в 8.1: 80729218 (учитывая переключение между окном с 7 на 8 = 2-3 сек.). А всё потому, что вышеуказанный скрипт указывает на текущее время системы в миллисекундах. В принципе можно использовать для подобных тестов как описаны выше(только не попадать в 00:00)

2. Говорят что в 8.0 переменные типа "дата" содержат миллисекунды, только это нигде не написано и приводят следующий код:

ДатаИсх = ТекущаяДата(); //простая дата+время
ДатаНов = ДатаИсх + 0.567; //дата+время+миллисекунды
Миллисекунды = (ДатаНов - ДатаИсх) * 1000; //вытаскиваем миллисекунды из даты

не знаю как на 8.0, а вот в 8.1 этот код и возвращает только 567

3. ВК "НЕТЛЕНКА" v 2.3 - http://infostart.ru/public/15589/ код:

Объект = Новый("Addin.System");
СтароеЗначение = Объект.МиллисекундСоСтарта();
Сообщить(СтароеЗначение);

отработал хорошо и показал результат: 7 452 125, хотя семерка показала 7715780(учитывая то, что обработка запустилась в 7.7 раньше чем в 8.1)

Из рассмотренных трех вариантов, можно с уверенностью остановится на 1-ом и 3-ем. 1-ый хорош тем, что может быть использован без внешней компоненты, а 3-ий хорош тем что это и есть число миллисекунд с момента включения ПК.


Бриллиантового кода Вам.

7 комментариев:

  1. Не совсем понятно зачем для учетных задач в 8 может понадобится знать миллисекунды. А для оценки производительности есть отличный инструмент отладки "Замер производительности".
    Видимо потому и нет аналога _GetPerformanceCounter()

    ОтветитьУдалить
  2. Мне было удобно так считать время отклика на запрос к веб из 1С. Время ответа в общем. Возможно есть еще какие-то способы ожидания времени отклика.

    ОтветитьУдалить
  3. Хм. Ну, врядли есть резон устанавливать таймауты меньше секунды при работе с вебом. Вопрос по-сути только в преобразовании ЧЧММСС к секундам. В этом смысле _GetPerformanceCounter() деействитльно удобнее. Но в восьмерке и разница дат даст секунды, ничего считать не надо, простое вычитание.

    ОтветитьУдалить
  4. Да. Вычитание дат очень даже подходит.

    ОтветитьУдалить
  5. 1С:Предприятие 8.2 (8.2.13.205)
    Метод:
    дд1 = ТекущаяДата();
    ...
    текст проги
    ...
    дд2 = ТекущаяДата();
    Миллисекунды = (дд2 - дд1) * 1000;

    Вытаскивает, к сожалению только сек помноженные на 1000!

    ОтветитьУдалить
  6. p.p.s В дополнение к предыдущему....
    Метод 3 -дает 100% результат для измерения работы кода в мсек!!!
    Известно, что "все дороги ведут к коммунизму...", но теперь можно выбрать кратчайшие !!!

    Спасибо автору блога!
    и Hadgehogs http://infostart.ru/public/15589/

    ОтветитьУдалить
  7. Согласен с Вами что НЕТЛЕНКА лучше всех отрабатывает в миллисекундах, но я стал обходится вычитанием дат. Как Вы и привели в коде, только без умножения на 1000. Просто получаю секунды.

    ОтветитьУдалить