views:

872

answers:

6

How to get micro second resolution timestamps on windows? I am loking for something better than QueryPerformanceCounter, QueryPerformanceFrequency (these can only give you an elapsed time since boot, and are not necessarily accurate if they are called on different threads - ie QueryPerformanceCounter may return different results on different CPUs. There are also some processors that adjust their frequency for power saving, which apparently isn't always reflected in their QueryPerformanceFrequency result.)

There is this, http://msdn.microsoft.com/en-us/magazine/cc163996.aspx but it does not seem to be solid. This looks great but its not available for download any more. http://www.ibm.com/developerworks/library/i-seconds/ This is another resource. http://www.lochan.org/2005/keith-cl/useful/win32time.html But requires a number of steps, running a helper program plus some init stuff also, I am not sure if it works on multiple CPUs

Also looked at the Wikipedia link on the subject which is interesting but not that useful. http://en.wikipedia.org/wiki/Time_Stamp_Counter

If the answer is just do this with BSD or Linux, its a lot easier thats fine, but I would like to confirm this and get some explanation as to why this is so hard in windows and so easy in linux and bsd. Its the same damm hardware...

+8  A: 

QueryPerformanceCounter QueryPerformanceFrequency

processor speed resolution

Just be careful with multi threaded, each core on a processor can have it's own counter.

Edit:

some more info:

http://www.lochan.org/2005/keith-cl/useful/win32time.html

Edit: If you do end up having to resort to this method: when I was trying to manually write data to a serial port (for an IR transmitter) I found that setting the process and thread priority to maximum (real time) greatly improved it's reliability (as in no errors), this is something that had to have a resolution of around 40khz if I remember too, so It should remain accurate enough for millisecond res.

matt
These can only give you an elapsed time since boot, and are not necessarily accurate if they are called on different threads - ie QueryPerformanceCounter may return different results on different CPUs. There are also some processors that adjust their frequency for power saving, which apparently isn't always reflected in their QueryPerformanceFrequency result.
kibibu
@Kibibu Exactly. I hinted that I needed something better than QueryPerformanceCounter QueryPerformanceFrequency in the question but did not elaborate why. Thanks for pointing this out.
Nikhil
@kibibu, if that's important then you have make the code run on a particular processor. I forget what that's called....is it processor affinity?
kenny
@kenny, yeah, processor affinity. this is the method I have used to do all my high precision stuff (such as profiling) anyway yeah, I should have read the msdn link first, it suggest this as a solution and then explains how it's not perfect.@Nikhil: I'm curios as to why you need this?theoretically all PCs have a system clock that maintains time when the processor is powered down. I don't know what the resolution of that would be, or how to get it.
matt
+1 for the correct reply. I know the correct reply is not always the wanted reply. QPC is the highest res timer available on a standard windows distro - unless you want to install custom hardware/drivers, the limits of QPC are what you need to work around.
Chris Becke
+1 - this is the way to do it with Windows. The counters will be accurate within the same threads, and if you need accuracy across threads you'll just have to use processor affinity. I know this is how most games calculate game frames.
JonM
I've removed my downvote for this answer - I was sure there were better alternatives if you didn't need nanosecond accuracy, but milliseconds is as good as it gets for the various methods that return an actual time. Unfortunately I can't switch to an upvote now...Thread affinity is indeed the thing, just make sure you aren't calling this from across multiple threads without setting them all to the same processor. There are still (apparently) problems with some versions of SpeedStep and similar. As is usually the case, the right answer depends on the application.
kibibu
@matt: it's been a number of years since CPUs have an HPET that is *guaranteed to be consistent across any number of cores/threads*. Now if Windows allows access to it is another matter, but they exist and they're not your grandpa's RTC/PIT. Thread as to how to read the HPET under Windows: http://stackoverflow.com/questions/786324/is-the-hpet-directly-accessible-in-windows
Webinator
@WizardOfOddsthat question is answered with 'use the RDTSC instruction'. I don't know what you are talking about but I have used this instruction my self, and I can tell you it is just as bad if not worse than using QueryPerformanceCounter (which uses this instruction it's self some times), this somewhat confirmed by the fact that the answer had no upvotes while a comment under it saying DO NOT USE has 2.
matt
+4  A: 

1.Windows is not real-time O/S

2.Process on Multitasking O/S will need to yield its time to another thread/process, this gives some overhead for timing.

3.every function call will have overhead thus giving a little delay when returning the request.

4.furthermore calling system call will need your process to switch from user space mode to kernel space mode, which is relatively high latency. You can overcome this by running entire process in kernel mode (such as device driver code)

5.some O/S like linux or BSD are better, but still can not maintain accurate timing resolution to sub-microsecond (eg.nanosleep() on linux accuracy is ~1ms not <1ms), except you patch kernel to some specific scheduler that give your app. benefits

so I think, its better to adapt your application to follow those issues, such as by recalibrating your timing routine often, which is what your links provide. AFAIK, the highest timer resolution for windows is still GetPerformanceCounter/Frequency() regardless its accuracy. you can get better accuracy by running you timer pooling routine inside separate thread, and set that thread affinity to one core processor, and set the thread priority the highest you can get.

uray
+4  A: 

I don't think you're going to find a solution better than QueryPerformanceCounter. The standard technique is to set up your code to catch and discard backward time jumps and massive outliers that might result from a thread switching cpus. If you're measuring very small intervals (if not, then you don't need that precision), then it's not a common occurrence any way. Just make it a tolerable error rather than a critical error.

In the rare cases where you absolutely need to be sure that it never happens, then locking your threads down by setting the processor affinity mask is the only option.

Alan
+1  A: 

I've used the DateTimePrecise class from CodeProject:

http://www.codeproject.com/KB/cs/DateTimePrecise.aspx

The only problem I had with it is that it would give crazy results if I didn't call it at least every 10 seconds -- I think there was some sort of integer overflow internally -- so I have a timer which executes DateTimePrecise.Now every few seconds.

You should also run NTP on the machine if you want the times to be at all accurate.

Good luck...

Joe H
+3  A: 

QueryPerformanceCounter is the correct solution to this. Contrary to what you and some people answering you wrote, this call gives the correct answer even with multiprocessor systems (unless the system in question is broken), and it handles even changing CPU frequency. On most modern systems it is derived from rdtsc, but handling all those multi-cpu and frequency changing details for you. (It is significantly slower than rdtsc, though).

See QueryPerformanceCounter

On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL).

Suma
+1  A: 

I believe this is still useful: Sytem Internals: Guidelines For Providing Multimedia Timer Support.

It does a good job of explaining the various timers available and their limitations. It might be that your archenemy will not so much be resolution, but latency.

QueryPerformanceCounter will not always run at CPU speed. In fact, it might try to avoid RDTSC, especially on multi-processor(/multi-core) systems: it will use the HPET on Vista and later if it is available or the ACPI/PM timer. On my system (Win7 x64, dual core AMD) the timer runs at 14.31818MHz.

The same is true for earlier systems: "By default, Windows Server 2003 Service Pack 2 (SP2) uses the PM timer for all multiprocessor APIC or ACPI HALs, unless the check process to determine whether the BIOS supports the APIC or ACPI HALs fails." The problem is, when the check fails. This simply means that your computer/BIOS is broken in a way. Then you might either fix your BIOS (recommended), or at least switch to using the ACPI timer (/usepmtimer) for the time being.

It is easy from C# - without P/Invoke - to check for hi-res timer support with Stopwatch.IsHighResolution and then peek at Stopwatch.Frequency. It will make the necessary QPF call internally.

Also consider that if the timers are broken the whole system will go havoc and in general, behave strangely, reporting negative elapsed times, slowing down, etc. - not just your application.

This means that you can actually rely on QPC.

...and contrary to popular belief, QueryPerformanceFrequency() "cannot change while the system is running".

Edit: As the documentation on QueryPerformanceCounter() states, "it should not matter which processor is called" - and in fact the whole hacking around with thread affinity is only needed if the APIC/ACPI detection fails and the system resorts to using the TSC. It is a resort that should not happen. If it happens on older systems, there is likely a BIOS update/driver fix from the manufacturer. If there is none, the /usepmtimer boot switch is still there. If that fails as well, because the system does not have a proper timer apart from the Pentium TSC, you might in fact consider messing with thread affinity - even then, the sample provided by others in the "Community Content" area of the page is misleading as it has a non-negligible overhead due to setting thread affinity on every start/stop call - that introduces considerable latency and likely diminishes the benefits of using a high resolution timer in the first place.

Here is a recommendation on how to use them properly. Please consider that it is now 5 years old, and that time a less systems were fully ACPI compliant/supported - that is why while bashing it, the article goes into so much detail about TSC and how to work around its limitations by keeping an affine thread.

I believe it is a fairly hard task nowadays to find a common PC with zero ACPI support and no usable PM timer. The most common case is probably BIOS settings, when ACPI support is incorrectly set (sometimes sadly by factory defaults).

Anecdotes tell that 8 years ago, the situation was different in rare cases. (Makes a fun read, developers working around design "shortcomings" and bashing chip designers. To be fair, it might be the same way vice versa. :-)

andras
so "use QueryPerformanceCounter" ? wow, if only I'd thought of that...also, this still can return negative results even on my new core i7, so be wary. also, I don't think anyone is suggesting you would change the thread affinity just to call QueryPerformanceCounter and then change it back. just leave the thread set to one core permanently.
matt
@matt: I'm not saying that *you* - or anyone here in this thread - suggested changing thread affinity on each call. However the community content supplied right here, on this very page does just that: http://msdn.microsoft.com/en-us/library/ms644904%28VS.85%29.aspx
andras
@matt: as for your system using TSC: this will have an effect on lots of applications. (Namely, all that is using QPC/QPF.) Have you considered why it is not using other, more reliable time sources? What OS are you running? Linux people seemed to be clear on this some time ago: no PM timer, no high-res support."My timestamp counter is good. Why do I need ACPI for hrt?We do not trust TSC at all. Never ever."http://www.mail-archive.com/[email protected]/msg09341.html.
andras
@matt: so in fact, yes, use QPC - but make sure that it does not use RDTSC or you will end up with a nicely disguised API call to RDTSC.
andras
If you need HPET, make sure settings in the BIOS are correct.One that I came across is "ACPI HPET Table => Enabled."The other is "HPET Support => Enabled" then "HPET Mode => 32bit/64bit", depending whether you run Vista(Win7) x86 or x64.HPET: http://blog.fpmurphy.com/2009/07/linux-hpet-support.htmlHPET is Vista and up only.PM (ACPI) timers can be used on older systems as well.
andras
@andras: cool, I'll definitely check out the bios settings! I've certainly done QPC on at least one computer where the freq had nothing to do with the cpu clock, and was probably closer to the 14mhz mark. +1
matt
@matt: thanks. I'm eager to hear back from you. I've seen a few years old 8-way Xeon with the same problem. It was built before the then current revision of the ACPI spec finalized. Win2003 just couldn't decide what to use and fell back to the worst case (TSC). It was so much fun measuring the performance of our application on that... :-).
andras