Хоть завалящий таймер высокого (можно не очень) разрешения? Ну хоть до милисекундной точности?
А?
З.Ы. В арме я полный нуб
Модератор: Модераторы
pi@raspberrypi:~/tmp $ ./test_timers now
Testing the Now() function (cross/platform, ported from Delphi)...
0ms: 0
1ms: 1001
Total changes: 1001, cycles: 318806
The milisecond grid is too coarse! Measuring microseconds...
1000us: 1001
Total changes: 1001, cycles: 323298
pi@raspberrypi:~/tmp $ ./test_timers gtod
Testing the gettimeofday() function...
0ms: 0
1ms: 1001
Total changes: 1001, cycles: 1201564
The milisecond grid is too coarse! Measuring microseconds...
1us: 984382
2us: 1643
3us: 15
4us: 1
6us: 1
9us: 59
10us: 304
11us: 265
12us: 66
13us: 48
14us: 31
15us: 27
16us: 11
17us: 4
18us: 48
19us: 31
20us: 5
21us: 4
22us: 8
23us: 1
24us: 2
25us: 4
26us: 4
27us: 2
28us: 2
29us: 4
30us: 2
31us: 2
32us: 1
33us: 1
35us: 2
37us: 1
38us: 1
41us: 1
42us: 1
44us: 1
45us: 1
48us: 1
49us: 2
51us: 1
55us: 1
59us: 1
74us: 1
89us: 1
Total changes: 986994, cycles: 1202333
pi@raspberrypi:~/tmp $ ./test_timers cgt
Testing the clock_gettime() function...
Trying CLOCK_PROCESS_CPUTIME_ID... 0s, 1ns.
0ms: 0
1ms: 1001
Total changes: 1001, cycles: 502762
The milisecond grid is too coarse! Measuring microseconds...
2us: 293599
3us: 134160
4us: 832
5us: 789
6us: 166
7us: 7
13us: 2
14us: 2
15us: 1
16us: 2
17us: 40
18us: 23
19us: 10
20us: 2
21us: 4
22us: 1
23us: 1
25us: 2
26us: 1
27us: 1
31us: 1
34us: 1
35us: 1
37us: 1
43us: 1
46us: 1
58us: 1
59us: 1
Total changes: 429653, cycles: 429654
{$mode objfpc}
{$longstrings on}
{$apptype console}
{$coperators on}
program test_timers;
uses sysutils, classes, math
{$ifdef windows} , windows {$endif}
{$ifdef unix} , baseunix, unix
{$ifdef linux}, linux {$endif}
{$endif}
;
var what: string;
{$ifdef windows}
type
MMRESULT = UINT;
const
TIMERR_NOERROR = 0;
function timeBeginPeriod(x1: UINT): MMRESULT; stdcall; external 'winmm.dll' name 'timeBeginPeriod';
function timeEndPeriod(x1: UINT): MMRESULT; stdcall; external 'winmm.dll' name 'timeEndPeriod';
{$endif}
procedure TestNow;
var
btime: TDateTime;
prev, current: TDateTime;
i, m: integer;
a: array[0..1000] of int64;
total, cycles: int64;
begin
WriteLn('Testing the Now() function (cross/platform, ported from Delphi)...');
FillChar(a, sizeof(a), 0);
btime:= Now();
cycles:=0;
repeat
current:= Now();
if (cycles > 0) and (current <> prev)
then Inc(a[Math.max(0, Math.min(100, round((current - prev) * 86400000.0)))]);
prev:= current;
Inc(cycles);
until current > (btime + (1.0 / 86400.0));
m:= 1;
total:= 0;
for i:= 0 to 100 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
WriteLn(' ', i, 'ms: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
if ((1.0 * a[0]) > (0.1 * total)) or ((1.0 * a[1]) > (0.1 * total))
then begin
WriteLn(' The milisecond grid is too coarse! Measuring microseconds...');
FillChar(a, sizeof(a), 0);
btime:= Now();
cycles:=0;
repeat
current:= Now();
if (cycles > 0) and (current <> prev)
then Inc(a[Math.max(0, Math.min(1000, round((current - prev) * 86400000000.0)))]);
prev:= current;
Inc(cycles);
until current > (btime + (1.0 / 86400.0));
m:= 1;
total:= 0;
for i:= 0 to 1000 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
if a[i] > 0
then WriteLn(' ', i, 'us: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
end;
end;
procedure TestGetTickCount(use_tbp: boolean);
var
btime: Longint;
prev, current: Longint;
i, m: integer;
a: array[0..100] of int64;
total, cycles: int64;
begin
WriteLn('Testing the GetTickCount() function of Win API...');
{$ifndef windows}
WriteLn(' Not supported on this platform!');
Exit;
{$else}
FillChar(a, sizeof(a), 0);
if use_tbp then begin
Write(' Calling TimeBeginPeriod(1)... ');
if TimeBeginPeriod(1) <> TIMERR_NOERROR then begin
WriteLn('FAILURE!');
Exit;
end;
WriteLn('Ok')
end;
btime:= GetTickCount();
cycles:=0;
repeat
current:= GetTickCount();
if (cycles > 0) and (current <> prev)
then Inc(a[Math.max(0, Math.min(100, current - prev))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000);
if use_tbp then TimeEndPeriod(1);
m:= 1;
total:= 0;
for i:= 0 to 100 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
WriteLn(' ', i, 'ms: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
{$endif}
end;
procedure TestGetTimeOfDay;
{$ifdef unix}
var
btime: int64;
prev, current: int64;
i, m: integer;
a: array[0..1000] of int64;
total, cycles: int64;
tv: timeval; //record tv_sec:time_t; tv_usec:clong; end;
{$endif}
begin
WriteLn('Testing the gettimeofday() function...');
{$ifndef unix}
WriteLn(' Not supported on this platform!');
Exit;
{$else}
FillChar(a, sizeof(a), 0);
fpgettimeofday(@tv, NIL);
btime:= tv.tv_sec * 1000 + (tv.tv_usec div 1000);
cycles:= 0;
repeat
fpgettimeofday(@tv, NIL);
current:= tv.tv_sec * 1000 + (tv.tv_usec div 1000);
if (cycles > 0) and (current <> prev)
then Inc(a[Math.max(0, Math.min(100, current - prev))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000);
m:= 1;
total:= 0;
for i:= 0 to 100 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
WriteLn(' ', i, 'ms: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
if ((1.0 * a[0]) > (0.1 * total)) or ((1.0 * a[1]) > (0.1 * total))
then begin
WriteLn(' The milisecond grid is too coarse! Measuring microseconds...');
FillChar(a, sizeof(a), 0);
fpgettimeofday(@tv, NIL);
btime:= tv.tv_sec * 1000000 + tv.tv_usec;
cycles:=0;
repeat
fpgettimeofday(@tv, NIL);
current:= tv.tv_sec * 1000000 + tv.tv_usec;
if (cycles > 0) and (current <> prev)
then Inc(a[Math.max(0, Math.min(1000, current - prev))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000000);
m:= 1;
total:= 0;
for i:= 0 to 1000 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
if a[i] > 0
then WriteLn(' ', i, 'us: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
end;
{$endif}
end;
procedure TestClockGetTime;
{$ifdef linux}
var
btime: int64;
prev, current: int64;
i, m: integer;
a: array[0..1000] of int64;
total, cycles: int64;
cid: clockid_t;
spec: timespec; //record tv_sec: Longint; tv_nsec: Longint; end;
{$endif}
begin
WriteLn('Testing the clock_gettime() function...');
{$ifndef linux}
WriteLn(' Not supported on this platform!');
Exit;
{$else}
FillChar(a, sizeof(a), 0);
cid:= CLOCK_PROCESS_CPUTIME_ID;
Write (' Trying CLOCK_PROCESS_CPUTIME_ID...');
if 0 <> clock_getres(cid, @spec) then begin
WriteLn ('FAIL!');
Exit;
end;
WriteLn (' ', spec.tv_sec, 's, ', spec.tv_nsec, 'ns.');
if spec.tv_sec <> 0 then begin
WriteLn ('EPIC FAIL: the seconds value is non-zero!');
Exit;
end;
clock_gettime(cid, @spec);
btime:= spec.tv_sec * 1000 + (spec.tv_nsec div 1000000);
cycles:= 0;
repeat
clock_gettime(cid, @spec);
current:= spec.tv_sec * 1000 + (spec.tv_nsec div 1000000);
if (cycles > 0) and (current <> prev)
then Inc(a[Math.max(0, Math.min(100, current - prev))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000);
m:= 1;
total:= 0;
for i:= 0 to 100 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
WriteLn(' ', i, 'ms: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
if ((1.0 * a[0]) > (0.1 * total)) or ((1.0 * a[1]) > (0.1 * total))
then begin
WriteLn(' The milisecond grid is too coarse! Measuring microseconds...');
FillChar(a, sizeof(a), 0);
clock_gettime(cid, @spec);
btime:= spec.tv_sec * 1000000 + (spec.tv_nsec div 1000);
cycles:=0;
repeat
clock_gettime(cid, @spec);
current:= spec.tv_sec * 1000000 + (spec.tv_nsec div 1000);
if (cycles > 0) and (current <> prev)
then Inc(a[Math.max(0, Math.min(1000, current - prev))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000000);
m:= 1;
total:= 0;
for i:= 0 to 1000 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
if a[i] > 0
then WriteLn(' ', i, 'us: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
if ((1.0 * a[0]) > (0.1 * total)) or ((1.0 * a[1]) > (0.1 * total))
then begin
WriteLn(' The microsecond grid is too coarse! Measuring nanoseconds...');
FillChar(a, sizeof(a), 0);
clock_gettime(cid, @spec);
btime:= int64(spec.tv_sec) * int64(1000000000) + spec.tv_nsec;
cycles:=0;
repeat
clock_gettime(cid, @spec);
current:= int64(spec.tv_sec) * int64(1000000000) + spec.tv_nsec;
if (cycles > 0) and (current <> prev)
then Inc(a[Math.max(0, Math.min(1000, current - prev))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000000000);
m:= 1;
total:= 0;
for i:= 0 to 1000 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
if a[i] > 0
then WriteLn(' ', i, 'ns: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
end;
end;
{$endif}
end;
{$if defined(CPUi386) or defined(CPUX86_64)}
{$define x86}
{$endif}
var q: int64;
{$ifdef x86}
{$asmmode intel}
procedure getnt;
begin
asm
{$ifdef cpu64}
pushf
push rdx
push rax
rdtsc
mov dword[q], eax
mov dword[q + 4], edx
pop rax
pop rdx
popf
{$else}
pushf
push edx
push eax
rdtsc
mov dword[q], eax
mov dword[q + 4], edx
pop eax
pop edx
popf
{$endif}
end;
end;
{$endif}
procedure TestRDTSC;
var
btime, prev, current: double;
factor: double;
i, m: integer;
a: array[0..1000] of int64;
total, cycles: int64;
qprev: int64;
t1: TDateTime;
begin
WriteLn('Testing the mighty RDTSC instruction, directly from the CPU!');
{$ifndef x86}
WriteLn(' Not supported on this platform!');
Exit;
{$else}
FillChar(a, sizeof(a), 0);
Write(' Measuring frequency... ');
t1:= Now();
getnt();
prev:= q;
repeat until (Now() - t1) > (1 / 86400);
getnt();
WriteLn (q - prev);
factor:= 1000.0 / (q - prev);
getnt();
btime:= 0;
current:= 0;
cycles:= 0;
repeat
qprev:= q;
getnt();
current+= (q - qprev) * factor;
if (cycles > 0) and (round (current - prev) <> 0)
then Inc(a[Math.max(0, Math.min(100, round(current - prev)))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000);
m:= 1;
total:= 0;
for i:= 0 to 100 do begin
if a[i] > 0 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
WriteLn(' ', i, 'ms: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
if ((1.0 * a[0]) > (0.1 * total)) or ((1.0 * a[1]) > (0.1 * total))
then begin
WriteLn(' The milisecond grid is too coarse! Measuring microseconds...');
FillChar(a, sizeof(a), 0);
factor *= 1000.0;
getnt();
btime:= 0;
current:= 0;
cycles:=0;
repeat
qprev:= q;
getnt();
current+= (q - qprev) * factor;
if (cycles > 0) and (round (current - prev) <> 0)
then Inc(a[Math.max(0, Math.min(1000, round(current - prev)))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000000);
m:= 1;
total:= 0;
for i:= 0 to 1000 do begin
if a[i] > 1000 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
if a[i] > 1000
then WriteLn(' ', i, 'us: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
if ((1.0 * a[0]) > (0.1 * total)) or ((1.0 * a[1]) > (0.1 * total))
then begin
WriteLn(' The microsecond grid is too coarse! Measuring nanoseconds...');
FillChar(a, sizeof(a), 0);
factor *= 1000.0;
getnt();
btime:= 0;
current:= 0;
cycles:=0;
repeat
qprev:= q;
getnt();
current+= (q - qprev) * factor;
if (cycles > 0) and (round (current - prev) <> 0)
then Inc(a[Math.max(0, Math.min(1000, round(current - prev)))]);
prev:= current;
Inc(cycles);
until current > (btime + 1000000000);
m:= 1;
total:= 0;
for i:= 0 to 1000 do begin
if a[i] > 1000 then m:= i;
total+= a[i];
end;
for i:= 0 to m do
if a[i] > 1000
then WriteLn(' ', i, 'ns: ', a[i]);
WriteLn (' Total changes: ', total, ', cycles: ', cycles);
end;
end;
{$endif}
end;
begin
what:= LowerCase(ParamStr(1));
if what = 'now'
then TestNow
else if what = 'tc'
then TestGetTickCount(false)
else if what = 'tc-tbp'
then TestGetTickCount(true)
else if what = 'gtod'
then TestGetTimeOfDay
else if what = 'cgt'
then TestClockGetTime
else if what = 'rdtsc'
then TestRDTSC
else begin
WriteLn ('Usage: test_timers <timer>');
WriteLn (' where <timers> is:');
WriteLn (' now - the Now() function, ported from Delphi to all platforms');
WriteLn (' tc - GetTickCount() of Win API');
WriteLn (' tc-tbp - GetTickCount() + TimeBeginPeriod(1)');
WriteLn (' gtod - gettimeofday() function of Linux API');
WriteLn (' cgt - clock_gettime() function of Linux API');
WriteLn (' rdtsc - the RDTSC instruction of the x86 CPU');
end;
{$ifdef windows}
WriteLn('press Enter to close');
ReadLn;
{$endif}
end.
Cheb писал(а):clock_gettime() позорно слила gettimeofday() по быстродействию, почти в три раза :x
Дож писал(а):А если попробовать {$IFDEF LINUX}CLOCK_MONOTONIC_RAW{$ENDIF}, то какой результат по скорости получится?
Cheb писал(а):gettimeofday()
Cheb писал(а):для косвенного измерения загрузки видеокарты
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12