Issues about Time Routines on Win32 and *NIX

1. sleep

sleep is a frequently used function on the *NIX platforms. However, its counterpart on Win32 (_sleep or Sleep, of which the former are obsolete now) generally accept arguments in milliseconds instead of seconds of the POSIX way. To make things even more complicated, Borland C++ Compiler 5.5 defines _sleep (and sleep) in <dos.h>, which works in the POSIX way!

To solve this problem, I worked out a sleep.h, which wraps the routines and works in the POSIX way. If _NEED_SLEEP_ONLY is not defined, msleep (accepts milliseconds) and usleep (accepts microseconds) will be automatically defined too. Of course, usleep on Win32 will not have the accuracy of *NIX platforms.

2. timeval

Structure timeval and function gettimeofday are also widely used in POSIX programs. It is cumbersome to change them when porting a program from POSIX to Win32. That's the reason for this timeval.h. I don't think it needs much explanation. Just a note of interest: MSVC 6 seems to optimize it very well and inlines the quite complicated gettimeofday: a call in the unoptimized code takes 20 times more time than in the optimized code!

3. Measuring short periods

Although the emulated gettimeofday works quite well, it inherits some of the disadvantages of the underlying Win32 APIs. One of them is that it cannot measure periods shorter than 10 milliseconds. For this purpose we must use QueryPerformanceFrequency and QueryPerformanceCounter. You may consult MSDN if you do not know them. I will just give my pctimer.h now.

Some very short explanation. I use a new type pctimer_t to express short periods, which is a double expressing time in seconds. A short program will show the use and overhead of the pctimer call:

#include <stdio.h>
#include <stdlib.h>
#include "pctimer.h"

int main(int argc, char *argv[])
{
    int i, count;
    pctimer_t t1, t2;
    if (argc == 2)
        count = atoi(argv[1]);
    else
        count = 1000000;
    t1 = t2 = pctimer();
    for (i = 0; i < count; i++)
        t2 = pctimer();
    printf("%g\n", t2 - t1);
    return 0;
}

This program can measure periods shorter than one millisecond, which clock() (I used to use it to measure time) never achieves. The call itself takes about 1.7 microseconds on my 550-MHz Celeron ThinkPad (with MSVC; GCC takes longer). Oh, yes, maybe you will also have interest to know that the QueryPerformanceCounter call (and thus pctimer) takes less overhead on Windows 2000 than on Windows 98, or at least my tests show so.

All code here is considered in the public domain though I do wish my name could be retained if anyone used them. :-)

2002-2-26, Written by Wu Yongwei


This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 Licence.

Return to Main