timetest.pp :
- Код: Выделить всё
{$mode objfpc}
{$h+}
uses
SysUtils;
function doWork():string;
var tm1,tm2:tdatetime; counter:int64;
begin
counter:=0; tm1:=time;
repeat tm2:=time; inc(counter); until (tm2<>tm1);
result:='Delta time: '+formatdatetime('tt:zzz',tm2-tm1)+'; Cycles: '+inttostr(counter);
end;
begin
writeln(dowork());
end.
- Код: Выделить всё
...
Delta time: 0:00:00:016; Cycles: 4116
Delta time: 0:00:00:016; Cycles: 4318
Delta time: 0:00:00:015; Cycles: 4894
Delta time: 0:00:00:016; Cycles: 3580
...
Тот-же самый код в линуксе даёт гораздо более корректные результаты:
- Код: Выделить всё
...
Delta time: 00:00:00:001; Cycles: 55
Delta time: 00:00:00:001; Cycles: 65
Delta time: 00:00:00:001; Cycles: 69
Delta time: 00:00:00:001; Cycles: 1
Delta time: 00:00:00:001; Cycles: 64
Delta time: 00:00:00:001; Cycles: 4
Delta time: 00:00:00:001; Cycles: 9
...
Оба факта объясняются тем, что способ получения текущего времени в линуксе - это вызов системной функции gettimeofday, которая возвращает количество секунд и микросекунд, прошедшее с 1970 года. Эти данные приходится преобразовывать и усекать, т.к. тип TDateTime не содержит
микросекунды. Дополнительно, сам системный вызов gettimeofday под линуксом работает дольше, т.к. возвращает больше информации (в том числе - о локальной временной зоне) и дает более точные результаты, чем системный вызов getlocaltime вод виндовс. Модифицируем программу под юникс-специфику
timetest2.pp :
- Код: Выделить всё
{$mode objfpc}
{$h+}
uses
SysUtils,Unix;
function doWork():string;
var counter:int64;
tz1,tz2:timeval;
mksec1,mksec2:int64;
begin
fpgettimeofday(@tz1,nil);
counter:=0;
repeat
fpgettimeofday(@tz2,nil);
inc(counter);
mksec1:=int64(tz1.tv_sec)*1000000+tz1.tv_usec; mksec2:=int64(tz2.tv_sec)*1000000+tz2.tv_usec;
until (mksec2-mksec1>1000);
result:='Delta time: '+inttostr(mksec2-mksec1)+' microseconds;'+' Cycles: '+inttostr(counter);
end;
begin
writeln(dowork());
end.
Результаты нескольких последовательных запусков timetest2.pp:
- Код: Выделить всё
Delta time: 1007 microseconds; Cycles: 141
Delta time: 1004 microseconds; Cycles: 140
Delta time: 1006 microseconds; Cycles: 140
Delta time: 1003 microseconds; Cycles: 139
Общий вывод: для получения точного времени невозможно использовать функцию time в windows, в то время как в linux данная функции реализована корректно.
P.S. Для обеспечения равных условий опции компилятора freepascal были выставлены идентичными для Windows и Linux, сторонние приложения во время тестирования - far под windows, konsole(kde) - под linux, при этом загрузка процессора приложениями и системными службами была не более 1%.