Fog Creek Software
Discussion Board




Windows Timer precision?

I have two problems with windows' timer precision, which I can't seem to find _any_ documentation about searching through Google or MSDN. Perhaps some of you might be able to help:

First, I'm trying to get the exact time of day with millisecond precision. Yes, I really do need this - It is used correlate events in a distributed system. The multimedia / high performance timers are all relative to the computer's boot time. GetSystemTime(), ftime() and friends _look_ like they have microsecond resolution, but in fact have ~10ms or ~15ms on every machine I tried.

Does anyone know how to increase the system time resolution, or at the very least get a high precision time-of-day?

Second, after debugging for several days, I've come to the concolusion that WM_TIMER handling and/or SetTimer() calls make windows report _wrong_ times with ftime() / GetSystemTime() - it seems to report, at least for a while after the Timer event, the time at which the timer fired, rather than the wall time. In my case, this is a 100msec difference. I sort-of solved this by making the timer tick at 1ms, and doing nothing 99 out of 100 ticks.

Did anyone else see such a behaviour? Any MS insider reading this can confirm my speculation?

[And a rant: My Linux boxen have no problem keeping their clock synchronized to within 0.5ms; And the time-of-day functions on Linux/Solaris have microsecond and nanosecond resolution. Why can't Windows behave?]

Ori Berger
Tuesday, November 11, 2003

I believe there are some "high resolution" timers in Windows which you are supposed to use if you need, well, high resolution. 

Unfortunately, it's been a long time since I've done any Windows work so my memory on this is failing.

Almost Anonymous
Tuesday, November 11, 2003

Have you set up NNTP on all the Windows boxes? They sync the system clock to a designated atomic clock. That should keep you synchronized.

The multimedia timer is the highest-resolution timer available in Windows.

Here's some discussion about timer resolution:
http://www.microsoft.com/whdc/hwdev/platform/proc/mm-timer.mspx

Finally, just because a timer provides nanosecond resolution doesn't mean it provides nanosecond accuracy. For example, light only travels .3 m in a nsec. So if your computers are 5m of cable apart, then they *cannot* be synched within a nanosecond. Do a traceroute between your machines and see what the ping times are.

Philo

Philo
Tuesday, November 11, 2003

Right, teh multimedia timers. But I think Ori is saying he wan't the real live atomic clock in geneva sort of time, to the specified resolution because he is doing some sort of intricate synchronization between physically separated computers.

Ori, no can do. If you want a fine timer, you can get that, but the system clock is never going to be correct to within 1ms unless you can physically connect it to an atomic clock service.

Fortunately you can since the atomic clocks are sent via shortwave at near-light-speed which will give fyou the reseloution you need. You can buy a PCI card that recieves the clock signal and provides it to your application to the resolution you need. You will not find a software solution that works for this -- you need to get some hardware.

The other alternative is to connect directly to an atomic clock via modem lines and sync your clock that way periodically. that's a hardware solution too, of course. Depending on if you have shortwave reception or a phone line available will be the way you'll want to go. You can not get the resolution you want through net connections though because of packet delays.

Dennis Atkins
Tuesday, November 11, 2003

Philo, your solution won't work since he can't get that packet back with sufficient lack of litter or delay. We wants the actual atomic clock time of day to within 1 ms. No can do through the net, though it is possible via direct phone connection, or through shortwave, or through an actual physical wire connection with an atomic clock if he is in Denver or Geneva.

Dennis Atkins
Tuesday, November 11, 2003

litter-> jitter

Dennis Atkins
Tuesday, November 11, 2003

The normal clock has a resolution of 55ms, or 18.2 clicks per second.

For a high resolution timer look at QueryPerformanceCounter and QueryPerformanceFrequency. On many machines these are incredibly accurate counters.

Dennis Forbes
Tuesday, November 11, 2003

Dennis - agreed. I thought the issue was syncing each computer to every other one locally, *and* having them on accurate time (which you can do by having a local NNTP server which syncs with an atomic clock).

However, I didn't think that he might be talking about geographically distributed systems that need to be in sync, in which case you're right - the PCI card is the best way to go.

Philo

Philo
Tuesday, November 11, 2003

D. Forbes,

They are precise indeed but they are not synchronized to the atomic clock to within the required precision.

Dennis Atkins
Tuesday, November 11, 2003

Philo,

Right - if all the computers are local there are more ways to do it.

Dennis Atkins
Tuesday, November 11, 2003

Umm...If you need millisecond-precision time of day, across a distributed system, how do you keep the systems syncronized with one another? Clock drift is going to move them apart at a pretty good clip. Especially if one or more are turned off for any part of the interesting period (battery-backed clocks in PCs are notoriously inaccurate when running on batteries). Obviously if the outside world is giving you a simultaneous signal, this won't be a problem.

Why Windows doesn't give you more accurate timers: (Only a guess, as I was not there) Windows was originally developed on relatively low-capability hardware, and originally built on top of a low-capability OS (DOS). Frankly it didn't NEED good timing, so why waste the cpu or the manpower on it? When your purpose is mostly to be a good GUI, millisecond accurate time-of-day isn't an essential feature, and probably not worth the effort. WM_TIMER, for insance, was originally designed (if I'm not mistaken) for UI work - 1/100 of a second is plenty good enough for that.

How to get good timings: You could use the high-performance timer, and correlate it to 'real time' when your app starts up. That would give you good timing while the system is running. (You do need to be careful about overflows, though. I don't remember how big that timer is).

If you need REALLY good timings, and you can't just sync up the performance counters, then you might try a clock card. Having never needed one, I don't know where to go offhand. You might try national instruments.

Frankly, if you're app has that kind of hard realtime requirement, you might want to think twice about using Windows as the host platform - or at least invenstigate modifications that would make Windows more predictable. I know there used to be several companies that sold 'modified' versions of Windows NT for use in industrial control systems - they would basically configure NT and add some drivers and whatnot so that the things you had to have strict timing control over, you could GET strict timing control over.

Good luck!

Michael Kohne
Tuesday, November 11, 2003

One comment to the other posters: Acutally, it is possible to get better than 1 ms resolution relative to another machine. The xntp package uses some interesting algorithms to quite accurately sync computers, even over links with significant jitter. I've never looked into the algorithms, but I suspect it basically 'filters out' the jitter in it's connection to the time server.

Michael Kohne
Tuesday, November 11, 2003

Philo>> "NNTP server"

I don't think that means what you think it means. :)

NNTP == Net News Transport Portocol (i.e. Usenet)

NTP == Network Time Protocol

RocketJeff
Tuesday, November 11, 2003

ROFL! Good catch! Indeed, I was not trying to suggest he post time ticks to alt.time.at.the.tone.beep.beep.beep

Philo

Philo
Tuesday, November 11, 2003

> but I suspect it basically 'filters out' the jitter in it's connection to the time server.

Since you need at least 3 servers, presumably some kind of triangulation is going on.

Portabella
Tuesday, November 11, 2003

Ori,

If you try that xntp thing and it works within your constraints, let us know. It sounds like a pretty useful thing.

Dennis Atkins
Tuesday, November 11, 2003

One pretty cool way to keep accurate track of time is to use a GPS receiver. Back when I was a programmer masquerading as an engineer, I saw this done in electrical substations, to make sure that the timestamps on the fault logs were super-accurate. Not exactly a low-cost solution, though.

Rob VH
Tuesday, November 11, 2003

Several companies sell plug-and-play GPS-based NTP servers. (Google for "gps ntp server")

If you really need to get a synchronized timebase on multiple computers <1ms... The FireWire bus isochronous clock might work; it's 8000Hz and guaranteed to be in sync. Watch out for sub-par timers on some desktops though. (and don't even think about laptops - their reduced-speed power-save modes make timers go haywire)

Dan Maas
Tuesday, November 11, 2003

Erm... WM_TIMER messages are low priority, and can be discarded - i.e. they never stack in the message queue.

Don't use them for anything important.


Tuesday, November 11, 2003


is it mandatory to use windows for this app?

- sysinternals have some high precision timer articles
- qnx is a real real-time os, maybe on that platform it's easier

name not available
Wednesday, November 12, 2003

"alt.time.at.the.tone.beep.beep.beep"

Ooh! Ooh! I feel a "newgroup" coming on!


Wednesday, November 12, 2003

Thanks for the replies everyone.

All my machines are already NTP synched, to a local NTP server (which I occasionally sync to an official, "stratum 1" NTP server). When I check the Linux boxes, they _never_ go above 0.5ms apart (seldom over 0.1ms); The NTP server is smart enough to measure and eliminate any systematic drift.

The Windows boxes are a different thing; I'm using Win2K's built in NTP client to synchronize with the same local NTP server. But since the clock accuracy itself is limited to ~15ms, I get +-~8 ms drift on the average; Also, I've tried many registry tweaks, but I can't get it to compensate for systematic drift, or synchronize often enough to eliminate it.

High resolution performance counters, as I stated in the first post, are NOT helpful - they are machine relative. I have two machines, sitting side by side (connected through a total ~50m of wire, and a network switch - which puts a minimum of ~10us) . I need to correlate events between them, with ~1ms accuracy - they make nearly identical "observations" on collected data (that's coming in at hundreds of events per second), and I need to be able to tell, with good probability, where it appeared first. (No, I don't need absolute truth here - a 90% correctness rate is sufficient).

I'd happily drop Windows - this is a "soft real time" system, and Windows is fairing it much worse than Linux does, and that DOS would have done. Unfortunately, I have to use 3rd party DLLs which are only supported under Windows.

The 55ms clock resolution is no longer true - It was before the days of Windows 95 (perhaps before 3.1); It derived from the 1.193181Mhz crystal which was used to drive NTSC signals in the original PCg, divided by 65536 (highest possible divisor) to generate the timer clock. It was programmable even back then, and the original IBM / Microsoft Basic interpreter, for example, switched it to 4.5ms to provide more accurate times for it's music playing commands.

Maintaining accurate time is extremely simple, and does not cost much processor time (about 5 more cycles per task switch, plus 5 more cycles per request). Windows probably doesn't do it because it was never specced out, and not for any other reason.

I am surprised, though, that there is no documented or semi-documented way to speed the timer interrupt. I'm willing to pay with more task switched per second - my CPU usage is barely 1% on that machine. What I'd rather NOT do is implement my own NTP client that correlates high performance timers with the "real clock" time. Especially because the high performance timers are not reliable either (frequency can change without notice; They can jump backwards occasionally).

Thanks again for all the input.

Ori Berger
Wednesday, November 12, 2003

The sipelest solution could be a timestamping and forwarding service running on a separate machine, but maybe a combination of things from  http://www.apcmag.com/apc/v3.nsf/0/51D1D443A868B5E4CA256D47000FB994 can help you:

Set the IRQ Priority timer
Windows 2000/XP

Certain interrupts in Windows are more important than others, and you can set the OS to give certain IRQs a higher priority than others. This often increases system responsiveness. Navigate to
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\PriorityControl\ and add DWORD entries in the following format: IRQ#Priority, where # is the number of the IRQ to assign an enhanced priority to. So if you wanted to add IRQ 0, create the DWORD IRQ0Priority and set it to 1. Suggested IRQs to add by default are 0 and 8.

Change the process quanta settings
Windows 2000/XP

This one's for experts. The length of time which Windows executes one thread before it can switch to another thread is referred to as a quantum. These intervals can be fixed or variable, long or short, and can be biased towards foreground or background threads.

By editing the process quanta control settings you can get much more precise control over how your system schedules threading. For instance, if you've got a server that runs primarily background processes, you'll want to set the system to favour those and use long fixed-length timeslices to let everything run in as much a parallel fashion as possible.

The key that holds this information, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PriorityControl, has a value named Win32PrioritySeparation. This value is a bitmask, so setting it can be a little tricky. Start with the value 0 and add the following values to it.

If you want to set the ratio of foreground-to-background threads to:

3:1, add 2.
2:1, add 1.
1:1, add 0.

If you want to set the lengths of the quanta to:

Variable lengths: add 4.
Fixed lengths: add 8.

Variable-length quantas are useful if you have some processes that kick in and use a lot of CPU intermittently, but don't run non-stop. This way the OS can adjust the amount of time devoted so that timeslices are more evenly distributed between processes.

If you want to set the intervals for quanta to be:

Shorter: add 32.
Longer: add 16.

Just me (Sir to you)
Thursday, November 13, 2003

"I have to use 3rd party DLLs which are only supported under Windows"

Now if they were open source...

/stands well back
Thursday, November 13, 2003

Thanks! - I'll be investigating these options. (The timestamping server is possible, but I'm avoiding it so far, as I'm reluctant to add yet another point of failure).

Ori Berger
Thursday, November 13, 2003

/stands well back - well, yes, I avoid close source components if I can. However, this is a case in which I have no control and no option.

[A note to all the closed source / open source zealots - around here: I avoid close source components, purely for pragmatic reasons, such as the one described in this thread. There are enough religious wars for you to feed on in other threads].

Ori Berger
Thursday, November 13, 2003

Try using QueryPerformanceCounter and QueryPerformanceFrequency. It should work .

Menuka Jain
Thursday, June 03, 2004

*  Recent Topics

*  Fog Creek Home