Sign in to follow this  

Timing code - striking a balance

This topic is 4419 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm interested in a discussion of timing methods (Windows specific, and preferably .Net centric, though any Windows solution is fine) that bridge the gap between the guarenteed nature of using the tick count, and the precision of the performance timer. GetTickCount / System.Environment.TickCount offers the benefit that it works correctly on all systems - no hidden surprises. The downside is that it rolls over at 2^32 seconds (~49 days) and it has an accuracy as low as 20ms (50fps). The rollover can be fixed (a simple wrapper that checks if the latest value is smaller then the last value and adjusts accordingly), but the accuracy leaves a lot to be desired. QueryPerformanceCounter offers extremely high precision, but at a price - many new CPUs (in particular mobile CPUs) have been throwing QueryPerformanceCounter a curveball because of variable CPU speed and dualcore oddities. The root problem of course is that QueryPerformanceCounter is based on a mechanism that was never meant for timing, it was meant for profiling. It only had to return the right values on the developers machine, so that the developer could compare the performance of different code paths. I am wondering if anything inbetween exists; A method of timing offering 1-2ms precision, while avoiding CPU compatibility issues. If it also avoids rollovers (by providing a 64 bit result), even better.

Share this post


Link to post
Share on other sites
well, here's what I do. but first why I do it...

- I've found that the OS sometimes doesn't give time to my app, and there are periodic spike lags, so I've taken to doing a running boxcar smoothing.
- with that boxcar smoothing, you get a nicer resolution (temporal super-sampling?)
- clock() gives me 1ms resolution on Win2K and above (on the boxes I've tested, of course), 18.3ms on Win9x. However, anyone still running 9x is probably on a slower machine anyway, so my framerate won't be above 50 Hz anyway

so here's what I do (from memory):

initialization:
VirtualTime = 0.001 * clock();

per frame:
// for smoothing over 20 frames
VirtualTime += (0.001*clock() - VirtualTime) * 0.1;

then I use VirtualTime instead of actual clock values for all my computations. If you need the 32 => 64 bit extension, you do have to add an extra (if b
The literature I've read basically suggests that the best compromise between ease of coding and robustness is to use multiple timers. For example, poll GetTickCount once every 100ms, and use QPC in between to get more accurate results. Of course, I've never really worked with this myself. I assume you've seen Jan Wassenberg's Timing Pitfalls and Solutions.

Share this post


Link to post
Share on other sites
There are also the multimedia functions, timeGetTime. These functions have a default accuracy of around 5ms on windows 2000+, however you can improve the accuracy of the timer using timeBeginPeriod and timeEndPeriod. On windows 95 - ME it defaults to an accuracy of 1ms, and will not be affected by timeBeginPeriod and timeEndPeriod calls. It also suffers from the 49.71 day rollover

Share this post


Link to post
Share on other sites
Quote:
Original post by Washu
There are also the multimedia functions, timeGetTime. These functions have a default accuracy of around 5ms on windows 2000+, however you can improve the accuracy of the timer using timeBeginPeriod and timeEndPeriod. On windows 95 - ME it defaults to an accuracy of 1ms, and will not be affected by timeBeginPeriod and timeEndPeriod calls. It also suffers from the 49.71 day rollover


Looks good. As I said .Net (and actually meant C#) centric, here is how to use it in C#

Add
using System.Runtime.InteropServices;
Then in the class
[DllImport("winmm.dll")] public static extern UInt32 timeGetTime();

Your class now has a static method called timeGetTime that returns an unsigned 32bit integer.

Share this post


Link to post
Share on other sites
Quote:
GetTickCount / System.Environment.TickCount offers the benefit that it works correctly on all systems - no hidden surprises.


Actually, it may have the same bug as timeGetTime(): under high bus load, it may "slip backwards" and not advance in time with wallclock time.

This means that there is no single timer under Windows that is reliable to better than a second precision. QueryPerformanceCounter() is the best option for now -- most CPUs that do speed-stepping use either the PCI performance timer, or use the new High Performance Timers which are clock-frequency independent parts of the chip sets. In the future, all chip sets will likely have HPT, and thus QPC is the way to go if you use just one.

If you want to do better, you have to read all three (timeGetTime(), QPC, and RDTSC) and have them "vote" -- I have an article about that on my web site.

Share this post


Link to post
Share on other sites

This topic is 4419 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this