Test Report: Millisecond Resolution Timing With Visual C++ and Windows 95/98

Published: 1998-03-30

Updated: 1998-10-15

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.

Run-time Library Functions
  Average Error Resolution (Error x 2)
clock () 27 ms 55 ms
_ftime () 27 ms 55 ms
Win32 API Functions
  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 (&ltime1);
      do
    {
      _ftime (&timebuffer);
      finish = timebuffer.millitm;
      time (&ltime2);
      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