in reply to Time::Hires Granularity

Checking, I see that Time::HiRes1 is using GetSystemTimeAsFileTime() under Windows. Based on your results, it appears that this Win32 API call uses the same facility as GetTickCount() and has the same limitations.

GetTickCount() returns a 4-byte unsigned integer containing the number of milliseconds since the computer was booted (which wraps every 49.7 days). System "ticks" are the basis for scheduling in Win32. GetTickCount() is poorly named because it returns a count of milliseconds not a count of ticks. The duration of one "tick" depends on operating system version.

For Win98 and prior, the tick size is 60ms. For WinNT/Win2k, it is 10ms (same as for Solaris). For WinXP, it is 15ms. (Based on testing as I haven't found good documentation on these values.)

So even though GetSystemTimeAsFileTime() returns the time measured in 100-nanosecond intervals since January 1, 1601, it isn't any more accurate than between 10ms and 60ms.

The easiest way to get more accurate timings on Windows is to call QueryPerformanceFrequency() and QueryPerformanceCounter(). They each fill an 8-byte buffer with a __int64 value. The first fills it with the number of times the performance counter is incremented each second. The second fills it with the current value of this counter.

The resolution of the performance counter is much higher. One example showed it was 1193180Hz (it may well vary by hardware, I haven't looked into that too much).

Sorry, I don't have the time at the moment to find a module for you that exposes these APIs to Perl nor to write one using Win32::API nor XS. But it would probably be very cool (and not too difficult) to patch Time::HiRes so that it augemented its use of GetSystemTimeAsFileTime() with performance counter queries so that the resolution would be much, much higher.

Also note that Perl is compiled with access to GetTickCount() built-in so you can simply use Win32::GetTickCount() whenever you want (you don't even need to "use Win32" for it to work).

                - tye

1 Without the capital "R" (like in the node title) it is very similar to Time::Miller, but not as intoxicating.

Update: You could even have Time::HiRes optionally run a tight loop for around 10ms to 60ms when it is first loaded so that not only would timings of durations be much more accurate within this process, but timings would even be almost as accurate across processes...

  • Comment on Re: Time::Hires Granularity (tick size)

Replies are listed 'Best First'.
Re: Re: Time::Hires Granularity (tick size)
by superpete (Beadle) on Jan 01, 2004 at 18:25 UTC
    Re: wraps every 49.7 days - Interesting... I use Time::HiRes a lot on Win32, suppose I left a script running long enough, would it start to return incorrect times?

      No. The tick count and GetTickCount() wrap but neither GetSystemTimeAsFileTime() nor Time::HiRes do.

                      - tye
Re: Re: Time::Hires Granularity (tick size)
by Anonymous Monk on Dec 06, 2003 at 23:29 UTC
    """GetTickCount() returns a 4-byte unsigned integer containing the number of milliseconds since the computer was booted (which wraps every 49.7 days). """ That's patently ridiculous! What Windows sytem stays up for 49.7 days? :)