![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Измерение времени с точностью до мс [D7]
Andrew_Rostov © (2004-04-24 15:11:00)Задача измерить время отработки процедуры. Наиболее точный результат получился с помошью:
var
TimeStart,TimeEnd:TDateTime;
TimeElapsed:TTimeStamp;
procedure OnClick;
begin
TimeStart:=Time;
ProcedureA;
TimeEnd:=Time;
TimeElapsed:=DateTimeToTimeStamp(TimeEnd-TimeStart); //время в мс
end;
При построении диаграммы времени выполнения получил ступеньки с высотой около 16 мс. Возможная причина - насколько я помню, системный таймер срабатывает каждые 16 мс.
Возможно ли в принцине измерять отрезки времени длиной меньше 16 мс?
panov (2004-04-25 16:51:00) [1]function TickCount:Int64;
begin
QueryPerformanceCounter(Result);
end;
function DeltaTickToSeconds(const Delta: Int64):Double;
var
TickFreq: Int64;
begin
QueryPerformanceFrequency(TickFreq);
Result := Delta/TickFreq;
end;
var
DeltaCounter: int64;
begin
DeltaCounter := TickCount;
MyProc; //измеряемая процедура
DeltaCounter := TickCount-DeltaCounter
ShowMessage(FloatToStr(DeltaCounter)+' secouds');
Andrew_Rostov (2004-04-25 16:29:00) [2]Насколько я понимаю для использования нужно:
1) поместить этот код в файл и прописать в uses имя этого файла
2) объявить глобальную переменную My_Timer:THRTimer;
3) при создании формы вызвать My_Timer.Create;
4) для измерения времени делать следующее:
My_Timer.StartTimer;
ProcedureA;
TimeElapsed:=My_Timer.ReadTimer;
5) при закрытии формы вызвать My_Timer.Free
Проблема в том, что при создании таймера получаем исключение на строке Exists := QueryPerformanceFrequency(QW);
Если же My_Timer.Create не вызывать, то при чтении значения таймера ClockRate будет равным 0 и получаем исключение деления на 0.
vengo (2004-04-25 13:09:00) [3]Unit HighTimer;
interface
Uses Windows;
Type
THRTimer = Class(TObject)
Constructor Create;
Function StartTimer : Boolean;
Function ReadTimer : Double;
private
StartTime : Double;
ClockRate : Double;
public
Exists : Boolean;
End;
implementation
Constructor THRTimer.Create;
Var
QW : TLargeInteger;
BEGIN
Inherited Create;
Exists := QueryPerformanceFrequency(QW);
ClockRate := LARGE_INTEGER(QW).QuadPart;
END;
Function THRTimer.StartTimer : Boolean;
Var
QW : TLargeInteger;
BEGIN
Result := QueryPerformanceCounter(QW);
StartTime := LARGE_INTEGER(QW).QuadPart;
END;
Function THRTimer.ReadTimer : Double;
Var
ET : TLargeInteger;
BEGIN
QueryPerformanceCounter(ET);
Result := 1000000*( LARGE_INTEGER(ET).QuadPart - StartTime)/ClockRate;
END;
end.
Andrew_Rostov (2004-04-24 17:19:00) [4]Спасибо, а можно по подробнее о QueryPerformanceCounter() + QueryPerformanceFrequency() или GetTickCount?
Задача даже не в том, чтобы точно посчитать время отработки, а чтобы избавиться от "квантования" результатов на 16 мс отрезки времени - на графике зависимости времени работы от объема данных слишком явно видны ступеньки.
N170 (2004-04-24 16:56:00) [5]Ещё как вариант - QueryPerformanceCounter() + QueryPerformanceFrequency(). Там и точность и стабильность.
(Забыли?!)
evvcom (2004-04-24 16:51:00) [6]Во время выполнения ProcedureA могут и скорее всего будут выполняться и другие процедуры других потоков, других процессов. Так что точного чистого времени выполнения процедуры в виндах получить не получится.
panov (2004-04-24 16:36:00) [7]Используй GetTickCount.
Anatoly Podgoretsky (2004-04-24 15:27:00) [8]Измерить можно, стабильность получить нельзя
Kerk (2004-04-24 15:16:00) [9]Измерять можно с точностью до 20мс.