Problems with QueryPerformanceCounter on Windows Server 2003 Multi-Processor Hyper-V guests? Here’s why.

A friend of mine from another group came to me with a problem he’s been having on some Windows Server 2003 guests.

They’re doing some nifty stuff with the .NET Stopwatch() class, and some WPF animations, which uses the QueryPerformanceCounter Win32 API to figure out the timing during the animations.  Apparently, when they run their code in Hyper-V, the animations look sort of… not good.

They’re using Windows Server 2003 SP2 x86, which has been allocated two virtual processors.

It turns out that our performance guru, Tony Voellm, has already encountered something like this.  From Tony’s blog post:

The root issue comes about from the Win32 QueryPerformanceCounter function. By default it uses a time source called the TSC. This is a CPU time source that essentially counts CPU cycles. The TSC for each (virtual) processor can be different so there is no guarantee that reading TSC on one processor has anything to do with reading TSC on another processor. This means back to back reads of TSC on different VP's can actually go backwards. Hyper-V guarantees that TSC will not go backwards on a single VP.

The fix for this is to modify the guest’s BOOT.INI file by adding the /USEPMTIMER switch to your operating system’s boot entry.  This tells the system to use a different timer for QueryPerformanceCounter-related tasks, and should alleviate the problem.

Update: It looks like some people are seeing this as an error in their event logs.  The event number is 1054, and the event source is UserEnv.  This is the same problem with the same solution, it's just a different way of showing up. 

-mk