+7 (495) 229-0436   shopadmin@itshop.ru 119334, г. Москва, ул. Бардина, д. 4, корп. 3
 
 
Вход
 
 
Каталог
 
 
Подписка на новости
Новости ITShop
Windows 7 и Office: Новости и советы
Обучение и сертификация Microsoft
Вопросы и ответы по MSSQLServer
Delphi - проблемы и решения
Adobe Photoshop: алхимия дизайна
 
Ваш отзыв
Оцените качество магазина ITShop.ru на Яндекс.Маркете. Если вам нравится наш магазин - скажите об этом Google!
 
 
Способы оплаты
 
Курс расчета
 
 1 у.е. = 66.88 руб.
 
 Цены показывать:
 
 
 
 
  
Новости, статьи, акции
 

Delphi: как измерить точное время выполнения операции?

06.02.2018 13:04

Точное время измерения выполнения операции в Delphi может пригодится во многих случаях, начиная от самого простого - показать пользователю время, затраченное на выполнение длительной операции (здесь, кстати, высокая точность нужна редко) и, заканчивая, ситуациями, когда в целях оптимизации программы нам необходимо выявить в программе наиболее "узкие" места в которых программа "застревает" на длительный промежуток времени. В основном, последняя ситуация характерна при разработке программ, использующих и обрабатывающих большие массивы данных, когда скорость выполнения операций выходит, если не на первое, то на одно из первых мест в требованиях к приложению.
Есть несколько способов узнать время выполнения операций в Delphi и все эти способы, в принципе, рассмотрены как в Сети, так и моем блоге. Поэтому представленная ниже статья - это лишь объединение всех возможных способов измерения времени в Delphi и опытный Delphi-программист здесь врядли встретит что-то новое для себя.

Способ №1 - самый простой. Используем функцию Now()

Самый простейший и наименее точный способ измерить время, затраченное на выполнение какой-либо операции в Delphi - воспользоваться функцией Now() из модуля System.SysUtils .

Исходный код может выглядеть, например, так:

uses System.DateUtils; .... var Start, Stop: TDateTime; Elapsed: int64; begin Start:=Now; //засекли начало выполнения операции DoSomething;//выполняем что-либо Stop:=Now; //засекли окончание выполнения операции Elapsed:=SecondsBetween(Start, Stop);//время в секундах end;

uses System.DateUtils; .... var Start, Stop: TDateTime; Elapsed: int64; begin Start:=Now; //засекли начало выполнения операции DoSomething;//выполняем что-либо Stop:=Now; //засекли окончание выполнения операции Elapsed:=SecondsBetween(Start, Stop);//время в секундах end;

Вполне вероятно, что у вас может возникнуть резонный вопрос: почему я использовал в примере SecondsBetween() , а не, например, MilliSecondsBetween() для большей точности? Сделал я это, опираясь исключительно, на описание функции Now() в официальной справке по Delphi, которая гласит следующее: "Несмотря на то, что в TDateTime могут передаваться миллисекунды, Now() имеет точность до ближайшей секунды". То есть, если использовать Now() , то определять интервал времени с точностью до миллисекунд - не имеет смысла.

Способ №2 - используем Windows API. Функция GetTickCount().

Функция GetTickCount() не имеет параметров и возвращает количество миллисекунд, прошедших с момента запуска системы. Судя по официальной справке Microsoft, разрешение функции GetTickCount() ограничено разрешением системного таймера, которое обычно находится в диапазоне от 10 до 16 миллисекунд. При этом, счётчик миллисекунд будет обнулен, если система запущена более 49,7 дней.
В принципе, пример использования этой функции похож на предыдущий:

var Start, Stop: cardinal; Elapsed: cardinal; begin Start:=GetTickCount; //засекли начало выполнения операции DoSomething;//выполняем что-либо Stop:=GetTickCount; //засекли окончание выполнения операции Elapsed:=Stop-Start;//время в миллисекундах end;

var Start, Stop: cardinal; Elapsed: cardinal; begin Start:=GetTickCount; //засекли начало выполнения операции DoSomething;//выполняем что-либо Stop:=GetTickCount; //засекли окончание выполнения операции Elapsed:=Stop-Start;//время в миллисекундах end;

Так, используя функцию GetTickCount() мы можем засечь время выполнения операции в Delphi с точностью до миллисекунды. Если и такая точность Вам не подходит и необходимо измерить интервал времени ещё точнее, то следующий способ - для вас.

Способ №3 - продолжаем использовать Windows API. Функции QueryPerformanceCounter и QueryPerformanceFrequency

QueryPerformanceCounter - извлекает текущее значение счетчика производительности, которое представляет собой метку времени с высоким разрешением (<1 мкс), которая может использоваться для измерения временных интервалов.
QueryPerformanceFrequency - извлекает частоту счетчика производительности. Частота счетчика производительности фиксируется при загрузке системы и согласована во всех процессорах,поэтому значение нужно запрашивать только при инициализации приложения, а результат может быть кэширован.

Для того, чтобы воспользоваться этими функциями для отсчёта интервала времени, затраченного на выполнение какой-либо операции в Delphi нам необходимо оформить исходный код, например, таким образом:

var iCounterPerSec: TLargeInteger; T1, T2: TLargeInteger; //значение счётчика ДО и ПОСЛЕ операции begin QueryPerformanceFrequency(iCounterPerSec);//определили частоту счётчика QueryPerformanceCounter(T1); //засекли время начала операции   DoSomething; //выполнили что-то   QueryPerformanceCounter(T2);//засекли время окончания ShowMessage(FormatFloat('0.0000', (T2 - T1)/iCounterPerSec) + ' сек.');//вывели количество секунд на выполнение операции end;

var iCounterPerSec: TLargeInteger; T1, T2: TLargeInteger; //значение счётчика ДО и ПОСЛЕ операции begin QueryPerformanceFrequency(iCounterPerSec);//определили частоту счётчика QueryPerformanceCounter(T1); //засекли время начала операции DoSomething; //выполнили что-то QueryPerformanceCounter(T2);//засекли время окончания ShowMessage(FormatFloat('0.0000', (T2 - T1)/iCounterPerSec) + ' сек.');//вывели количество секунд на выполнение операции end;

С полученными значениями T1 и T2 можно "играться" как угодно, например, выводить отдельно минуты/секунды/миллисекунды и т.д. тут всё зависит от ваших потребностей и желаний, я же показал наиболее простой пример использования счётчика с высоким разрешением в Delphi.

Способ №4 - используем возможности Delphi. Модуль System.Diagnostics

Модуль этот появился в Delphi уже достаточно давно (могу ошибаться, но, по-моему с Delphi XE-XE2). В модуле представлена всего одна запись (record) - TStopwatch , которая является ни чем иным, как удобной "обёрткой" для использования таймеров высокого разрешения из примера выше. Судя по достаточно скромной справке, TStopwatch использует функциональные возможности, зависящие от операционной системы, для получения доступа к таймерам с высоким разрешением, если они доступны. Если таймеры с высоким разрешением в ОС недоступны, то используются обычные таймеры.

Несмотря на то, что TStopwatch - это запись, для корректного использования всё же необходимо вызывать метод Create или StartNew .

Описание TStopwatch следующее:

TStopwatch = record strict private class var FFrequency: Int64; class var FIsHighResolution: Boolean; class var TickFrequency: Double; strict private FElapsed: Int64; FRunning: Boolean; FStartTimeStamp: Int64; function GetElapsed: TTimeSpan; function GetElapsedDateTimeTicks: Int64; function GetElapsedMilliseconds: Int64; function GetElapsedTicks: Int64; class procedure InitStopwatchType; static; public class function Create: TStopwatch; static; class function GetTimeStamp: Int64; static; procedure Reset; procedure Start; class function StartNew: TStopwatch; static; procedure Stop; property Elapsed: TTimeSpan read GetElapsed; property ElapsedMilliseconds: Int64 read GetElapsedMilliseconds; property ElapsedTicks: Int64 read GetElapsedTicks; class property Frequency: Int64 read FFrequency; class property IsHighResolution: Boolean read FIsHighResolution; property IsRunning: Boolean read FRunning; end;

TStopwatch = record strict private class var FFrequency: Int64; class var FIsHighResolution: Boolean; class var TickFrequency: Double; strict private FElapsed: Int64; FRunning: Boolean; FStartTimeStamp: Int64; function GetElapsed: TTimeSpan; function GetElapsedDateTimeTicks: Int64; function GetElapsedMilliseconds: Int64; function GetElapsedTicks: Int64; class procedure InitStopwatchType; static; public class function Create: TStopwatch; static; class function GetTimeStamp: Int64; static; procedure Reset; procedure Start; class function StartNew: TStopwatch; static; procedure Stop; property Elapsed: TTimeSpan read GetElapsed; property ElapsedMilliseconds: Int64 read GetElapsedMilliseconds; property ElapsedTicks: Int64 read GetElapsedTicks; class property Frequency: Int64 read FFrequency; class property IsHighResolution: Boolean read FIsHighResolution; property IsRunning: Boolean read FRunning; end;

  • Свойство IsHighResolution указывает, основан ли таймер на счетчике производительности с высоким разрешением.
  • Метод Start() начинает измерять прошедшее время.
  • Метод Stop() останавливает измерение прошедшего времени.
  • Свойство ElapsedMilliseconds получает общее истекшее время в миллисекундах.
  • Свойство Elapsed получает истекшее время в виде TTimeSpan .

Воспользоваться возможностями TStopwatch также достаточно просто, например, так:

uses System.Diagnostics; ... var SW: TStopwatch; begin SW:=TStopwatch.StartNew; SW.Start;   DoSomething;   SW.Stop; ShowMessage(SW.Elapsed.TotalMinutes.ToString); end;

uses System.Diagnostics; ... var SW: TStopwatch; begin SW:=TStopwatch.StartNew; SW.Start; DoSomething; SW.Stop; ShowMessage(SW.Elapsed.TotalMinutes.ToString); end;

В представленном выше примере мы воспользовались TStopwatch и вывели количество минут (с дробной частью), пошедших на выполнение какой-то операции. В целом же, используя возможность TStopwatch.Elapsed можно выводить любые значения, ограниченные лишь возможностями TTimeSpan (см. справку).

Подведем итог

Итак, чтобы измерить точное время выполнения операции в Delphi, необходимо, прежде всего определиться с тем какая точность Вас устроит? Если достаточно, чтобы интервал времени определялся с точностью до секунды, то достаточно воспользоваться обычной, давно известной функцией Now() . Да, точность самая низкая, но, зато - просто.

Если ваше требование к точности измерения времени ограничивается миллисекундой - используйте GetTickCount() : просто, достаточно надежно (только, если вы не планируете измерять интервал времени больше 49,7 дней).

Если же требуется использовать самые точные методы измерения времени на выполнение операции, то тут либо связка функций QueryPerformanceCounter() и QueryPerformanceFrequency() , либо более удобный способ - использовать TStopwatch из модуля System.Diagnostics .

  
Помощь
Задать вопрос
 программы
 обучение
 экзамены
 компьютеры
Бесплатный звонок
ICQ-консультанты
Skype-консультанты

Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 
Популярные статьи
Резервное копирование Информационная безопасность Антивирусное ПО и защита от спама Eset Software
 
Бестселлеры
Курсы обучения "Atlassian JIRA - система управления проектами и задачами на предприятии"
Microsoft Office 365 для Дома 32-bit/x64. 5 ПК/Mac + 5 Планшетов + 5 Телефонов. Подписка на 1 год. Электронный ключ
Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
Microsoft Office для Дома и Учебы 2016. Все языки. Электронный ключ
Курс "Oracle. Программирование на SQL и PL/SQL"
Курс "Основы TOGAF® 9"
Microsoft Windows Professional 10 Sngl OLP 1 License No Level Legalization GetGenuine wCOA (FQC-09481)
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
Windows Server 2016 Standard
Курс "Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации"
Антивирус ESET NOD32 Antivirus Business Edition
Corel CorelDRAW Home & Student Suite X8
 

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям.

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

В нашем магазине вы можете приобрести лицензионное ПО выбрав необходимое из широкого спектра и ассортимента по самым доступным ценам. Наши менеджеры любезно помогут определиться с выбором ПО, которое необходимо именно вам. Также мы проводим учебные курсы. Мы приглашаем к сотрудничеству учебные центры, организаторов семинаров и бизнес-тренингов, преподавателей. Сфера сотрудничества - продвижение бизнес-тренингов и курсов обучения по информационным технологиям.



 

О нас

 
Главная
Каталог
Новинки
Акции
Вакансии
 

Помощь

 
Общая справка
Как оформить заказ
Тарифы доставки
Способы оплаты
Прайс-лист
Карта сайта
 

Способы оплаты

 

Проекты Interface Ltd.

 
Interface.ru   ITShop.ru   Interface.ru/training   Olap.ru   ITnews.ru  
 

119334, г. Москва, ул. Бардина, д. 4, корп. 3
+7 (495) 229-0436   shopadmin@itshop.ru
Проверить аттестат
© ООО "Interface Ltd."
Продаем программное обеспечение с 1990 года