Problems with QueryPerformanceCounter()

To make a computer game run at a consistent speed across different computers it is important to measure the elapsed time between frames and adjust the in-game computations accordingly. If this is not done the game will run too slow on a slower computer and too fast on a faster computer.

I had written some timing code which used the
QueryPerformanceCounter() and QueryPerformanceFrequency() Windows API functions which provide a high level of timing accuracy. The idea is to call QueryPerformanceFrequency() once to find out the frequency (in ticks per second) of the performance counter, and then, each frame, call QueryPerformanceCounter() to retrieve the current counter value. You can then work out the elapsed time between frames.

I had written a reusable timer class in C# for my Pong game (which I have just revisited). The code worked beautifully on my old P4 1.6Ghz and P4 2.8GHz, but when I ran it on my new Athlon 64 3800+ dual-core, the game behaved weirdly… Moving objects flickered and jumped back and forth.

I wrote a test program and determined that the QueryPerformanceCounter() function would occasionally return a counter value that was lower than the previous value by a significant amount! Shortly after this, the counter value would jump back up, putting it roughly back to where it should have been. This was causing the game to sometimes jump back in time by about an eighth of a second, then forward in time, resulting in the flicker affect.

Here is a screenshot from my test program. You can grab the C# source file here.
My test program for the QueryPerformanceCounter() function

My first thought was that something was wrong with my new PC! Nooo!! However a quick search of the web turned up that this problem is known. This thread on the Channel 9 forums describes the exact same problem and there is some good information in there. Apparently a Windows XP hotfix solved the problem for the poster. Also see this thread on CodeComments.com. MSDN also has some information here and here.

It seems this a problem that occurs on dual processor systems. Even if the hotfix solves the problem on a particular computer it is not really a solution because you can’t expect every user of your game to apply the hotfix. Not happy.

  Textile Help