Test Report: Millisecond Resolution Timing With Visual C++ and Windows 95/98
Copyright © 1998-2006 Chih-Hao Tsai (Email: )
Related Technical Reports
If You Use DJGPP and DPMI
If you use DJGPP and DPMI, check this out:
PCTIMER: Millisecond Resolution Timing With DJGPP V2 and DPMI
Summary
Virtually all cognitive psychology experiments require a millisecond resolution timing routine. In the good old MS-DOS days, it was easy to achieve this by increasing the frequency of hardware interrupt IRQ0 (int 8h), at the cost of increased instability of the whole system. Today, most people have already moved from MS-DOS to Windows 95/98 operating system. Since Windows 95 a such a complex system, in general a programmer cannot (or is not allowed to) intrude into lower levels of the system.
In fact, both the standard C run-time library and the Win32 API provide some timing functions. But we do not know how accurate they are. Two run-time library functions and two Win32 API functions from Microsoft Visual C++ Version 4.0 were tested on a Windows 95 machine with a standardized procedure for their quality (in terms of the resolution they can achieve). It was found that the two run-time library functions were basically at the same precision level: 18.2 Hz (resolution = 55 ms). The two Win32 API functions performed better than the run-time library functions, but only one of them reached near-millisecond resolution. It was concluded that only the Multimedia Timer is qualified to be used in psychological experiments.
Average Error | Resolution (Error x 2) | |
---|---|---|
clock () | 27 ms | 55 ms |
_ftime () | 27 ms | 55 ms |
Average Error | Resolution (Error x 2) | |
---|---|---|
GetTickCount () | 10 ms | 20 ms |
Multimedia Timer (winmm.lib) | 1 ms | 2 ms |
Run-time Library Functions
clock ()
Program
#include <time.h> #include <stdlib.h> #include <stdio.h> void main (void) { clock_t start, finish; int i; long int duration; for (i = 100; i <= 120; i++) { start = clock (); while (clock () < (start + i)); finish = clock (); duration = finish - start; printf ("expected:%d actual:%ld\n", i, duration); } }
Output
expected:100 actual:110 expected:101 actual:110 expected:102 actual:110 expected:103 actual:110 expected:104 actual:110 expected:105 actual:110 expected:106 actual:110 expected:107 actual:110 expected:108 actual:110 expected:109 actual:110 expected:110 actual:110 expected:111 actual:160 expected:112 actual:170 expected:113 actual:160 expected:114 actual:170 expected:115 actual:160 expected:116 actual:170 expected:117 actual:160 expected:118 actual:170 expected:119 actual:160 expected:120 actual:160
_ftime()
Program
#include <time.h> #include <sys/timeb.h> #include <stdlib.h> #include <stdio.h> void main (void) { struct _timeb timebuffer; time_t ltime1, ltime2; int i, start, finish, duration; for (i = 100; i <= 120; i++) { _ftime (&timebuffer); start = timebuffer.millitm; time (<ime1); do { _ftime (&timebuffer); finish = timebuffer.millitm; time (<ime2); duration = finish - start; if (duration < 0) duration += 1000; } while (duration < i); printf ("expected:%d actual:%ld\n", i, duration); } }
Output
expected:100 actual:110 expected:101 actual:110 expected:102 actual:110 expected:103 actual:110 expected:104 actual:110 expected:105 actual:110 expected:106 actual:110 expected:107 actual:110 expected:108 actual:110 expected:109 actual:110 expected:110 actual:110 expected:111 actual:160 expected:112 actual:170 expected:113 actual:160 expected:114 actual:170 expected:115 actual:160 expected:116 actual:170 expected:117 actual:160 expected:118 actual:170 expected:119 actual:160 expected:120 actual:170
Win32 API Functions
GetTickCount()
Program
#include <windows.h> #include <stdio.h> void main (void) { DWORD start, finish, duration, i; for (i = 100; i <= 120; i++) { start = GetTickCount (); while (GetTickCount () < (start + i)); finish = GetTickCount (); duration = finish - start; printf ("expected:%d actual:%ld\n", i, duration); } }
Output
expected:100 actual:103 expected:101 actual:128 expected:102 actual:110 expected:103 actual:110 expected:104 actual:110 expected:105 actual:122 expected:106 actual:109 expected:107 actual:109 expected:108 actual:111 expected:109 actual:128 expected:110 actual:117 expected:111 actual:124 expected:112 actual:124 expected:113 actual:123 expected:114 actual:123 expected:115 actual:125 expected:116 actual:123 expected:117 actual:124 expected:118 actual:123 expected:119 actual:124 expected:120 actual:124
Multimedia Timer (winmm.lib)
Program
#include <stdio.h> #include <windows.h> #include <mmsystem.h> void main (void) { TIMECAPS resolution; DWORD start, finish, duration, i; if (timeGetDevCaps (&resolution, sizeof (TIMECAPS)) == TIMERR_NOERROR) { printf ("Minimum supported resolution = %d\n", resolution.wPeriodMin); printf ("Maximum supported resolution = %d\n", resolution.wPeriodMax); } if (resolution.wPeriodMin <= 1) { if (timeBeginPeriod (1) == TIMERR_NOERROR) { for (i = 100; i <= 120; i++) { start = timeGetTime (); while (timeGetTime () < (start + i)); finish = timeGetTime (); duration = finish - start; printf ("expected:%d actual:%ld\n", i, duration); } timeEndPeriod (1); } } }
Output
Minimum supported resolution = 1 Maximum supported resolution = 65535 expected:100 actual:105 expected:101 actual:117 expected:102 actual:102 expected:103 actual:111 expected:104 actual:104 expected:105 actual:111 expected:106 actual:106 expected:107 actual:107 expected:108 actual:108 expected:109 actual:109 expected:110 actual:110 expected:111 actual:111 expected:112 actual:112 expected:113 actual:113 expected:114 actual:114 expected:115 actual:115 expected:116 actual:116 expected:117 actual:117 expected:118 actual:118 expected:119 actual:119 expected:120 actual:120