Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Модуль для удобного замера точных интервалов времени  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1112
Разработал модуль для удобного замера точных интервалов времени.
Ссылка на модуль: https://github.com/loginov-dmitry/multithread/blob/master/CommonUtils/TimeIntervals.pas

Основу модуля составляет record TTimeInterval, в котором имеется метод Start для запуска замера, Stop для останова замера и набор методов ElapsedXXX, позволяющих определить, сколько прошло времени с начала замера. Можно использовать в Delphi 2007 и более новых версиях. Текущая реализация - только под Windows.

Вот объявление структуры TTimeInterval:
type
  { TTimeInterval is designed to accurately measure time,
     passed after the start of measurement.
     Attention! Microsecond measurements
     performed with an error of several microseconds (despite
     using the variable PerformanceIgnoredTicks }
  TTimeInterval = record
  private
    FStartCounter: Int64;
    FIsRunning: Boolean;
    FElapsedTicks: Int64;
  public
    // Starts measuring
    procedure Start;

    // Finishes measuring. Updates the FElapsedTicks field. After the Stop method
    // is called, the ElapsedXXX methods will return the value stored in FElapsedTicks
    procedure Stop;

    // Returns the number of milliseconds after the start of measurement
    function ElapsedMilliseconds(AStartNew: Boolean = False): Int64;

    // Returns the number of microseconds after the start of measurements
    function ElapsedMicroseconds(AStartNew: Boolean = False): Int64;

    // Returns the number of seconds after the start of measurement
    function ElapsedSeconds(AStartNew: Boolean = False): Double;

    // Returns the number of ticks from the beginning of measurements
    function ElapsedTicks(AStartNew: Boolean = False): Int64;

    // Returns the time (TDateTime) elapsed since the start of measurement
    function ElapsedTime(AStartNew: Boolean = False): TDateTime;

    // Returns True if measurements are running.
    property IsRunning: Boolean read FIsRunning;
  end;


Как видно, результат замера времени можно получить в разных форматах: в миллисекундах, в микросекундах, в секундах, в отсчётах высокочастотного таймера, а также в стандартном TDateTime.

Пример использования:
procedure TForm1.Button2Click(Sender: TObject);
var
  p: TTimeInterval;
begin
  p.Start;
  Sleep(100);
  ShowMessageFmt('%s', [FormatDateTime('hh:nn:ss.zzz', p.ElapsedTime)]);
end;


Также можно остановить замер с помощью метода Stop, а вызов метода ElapsedXXX выполнить позже, в удобное время.
Высокая точность измерения (практически до микросекунды) обеспечивается за счёт запоминания длительности вызова QueryPerformanceCounter в переменной PerformanceIgnoredTicks (она учитывается при останове замера).

Кроме того, в модуле TimeIntervals имеется ещё одна структура, упрощающая логирование длительности серии операций: TTimeIntervalEvents. Пример её использования:
procedure TForm1.Button1Click(Sender: TObject);
var
  p: TTimeIntervalEvents;
begin
  p.StartEvent('Этап 1');
  Sleep(1);
  p.StopEvent('Этап 1');

  p.StartEvent('Этап 2');
  Sleep(20);
  p.StopEvent('Этап 2');

  ShowMessage(p.GetEventsAsString([eoWriteStartTime, eoWriteAllTime,
    eoUseMicroSec, eoWriteFromStart, eoWriteBegTime, eoWriteEndTime, eoWriteDate]));
  //ShowMessage(p.GetEventsAsString([eoUseMicroSec]));
end;


Я считаю, что данное решение более удобное и более продуманное, чем структура "секундомер", встроенная в современные версии Delphi (имеется ввиду TStopWatch из System.Diagnostics). TStopWatch - это, на мой взгляд, очень слабо продуманное решение, которое зачем-то срочно (с пивом за вечер) понадобилось сделать. Я сужу по его реализации в Delphi 10.3 (может в 10.4 что-то и улучшили).
Какие лично у меня замечания к TStopWatch:
1. Является секундомером, однако секунды измерять не умеет.
2. Ничего кроме миллисекунд (и неких условных единиц) не возвращает.
3. Не является интуитивно понятным. Думаете метода Start там достаточно для запуска секундомера? Нифига! Start там - это лишь продолжение замера, который был поставлен на паузу с помощью метода Stop. Stop - это не останов замера (как кажется из названия)! Это лишь постановка на паузу.
3.1 Для начала замера времени обязательно нужно вызвать метод TStopWatch.StartNew.
4. Какое отношение вообще секундомер имеет к диагностике? Могли бы сделать секундомер в виде компонента с циферками, было бы более логично!

Спасибо за внимание! :)
30 июн 20, 00:39    [22159339]     Ответить | Цитировать Сообщить модератору
 Re: Модуль для удобного замера точных интервалов времени  [new]
cptngrb
Member

Откуда:
Сообщений: 576
DmSer, очень хотелось бы микро и нано секунды
30 июн 20, 08:43    [22159424]     Ответить | Цитировать Сообщить модератору
 Re: Модуль для удобного замера точных интервалов времени  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1112
cptngrb
DmSer, очень хотелось бы микро и нано секунды

Насколько я понимаю, в наносекундах умеют измерять профилировщики. У меня нет задачи сделать профилировщик.
30 июн 20, 09:05    [22159435]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить