Balance CPU 1.0

Recently someone asked me what on earth the new QueryIdleProcessorCycleTime function in Windows Vista does. I can understand the confusion considering the documentation is just plain wrong, at least in terms of how the function is used. If you can look beyond the documentation then you will discover a function that is quite straightforward to use and actually quite interesting if you’re into performance and scalability. But first some background information.

Windows uses an interval timer to determine the time slices that the CPU allocates to different threads. These are absolute intervals that include time spent in the kernel servicing interrupts. On previous versions of Windows, the thread scheduler simply used these intervals to determine how much time each thread has been allotted even if a thread didn’t actually get its full slice due to interrupt processing and other factors. Well Windows Vista’s thread scheduler now takes advantage of the cycle counter register available on modern processors to accurately measure and provide the most accurate scheduling possible. Although Windows still uses interval-based scheduling, it can now more fairly determine whether a thread actually got to use a particular interval for any reasonable amount of time.

The QueryIdleProcessorCycleTime function, along with the QueryThreadCycleTime and QueryProcessCycleTime functions, provide applications with some insight into the number of cycles charged to different processes. In particular, QueryIdleProcessorCycleTime returns the number of cycles that each processor has spent idle. Think of this as the number of cycles consumed by each processor’s idle thread. As I mentioned, the QueryIdleProcessorCycleTime documentation is very misleading so here is a simple example illustrating how you might use it to display the number of clock cycles used by each processor’s idle thread.

SYSTEM_INFO info = { 0 };

CAtlArray<ULONG64> procs;

ULONG size = info.dwNumberOfProcessors * sizeof(ULONG64);


for (size_t index = 0; index < procs.GetCount(); ++index)
    ULONG64 idleCycles = procs[index];
    cout << "Processor " << index << ": " << idleCycles << endl;

As I hinted at before, this information can come in handy when trying to determine how effectively software is using the available processing power. Does your application effectively scale to multiple cores? Are some processors being “starved for attention” so to speak?

To allow me to visually inspect these characteristics I wrote the Balance CPU utility. Here is Balance CPU running on an Intel Core 2 Duo on Windows Vista.

Balance CPU provides a visual representation of the idle cycles for each processor. The bars are scaled to illustrate the relative differences in activity between processors. Shorter bars indicate more activity while longer bars indicate more time spent idle. A well balanced system will have all the bars roughly the same width while a system that does not scale well to the available processors will have an unbalanced set of processors with bars varying greatly in width.

You can also place the mouse pointer over a processor bar and a tool-tip will display the actual clock cycles for that processor.

Balance CPU also updates the display as well as the tool-tips every second so you can see how different applications and tasks make use of the available processing power. For fun, run my Max CPU utility side by side with Balance CPU and see how the clock cycles are burned up as you slide the stress level up and down.

The Balance and Reset buttons allow you to get a representation of clock cycles since a particular point in time. Say you want to see how well your application scales but don’t want previous idle cycles to bias the results. Simply click the Balance button and the processor bars will only present relative differences in activity since you clicked the Balance button. To reset the display simply click the Reset button.

Here is Balance CPU running on a Dual Intel Xeon with Hyper-Threading (4 logical processors) on Windows Server Longhorn with Max CPU to provide some imbalance.

Download the executable and save it to a local drive before running it. It requires Windows Vista or later and the .NET Framework 2.0 and will run natively as either a 32-bit or 64-bit process depending on your operating system.

© 2007 Kenny Kerr

1 Comment

Comments have been disabled for this content.