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