I’ve seen dozens of reproductions of the same code on the internet showing how to measure CPU utilization on a Windows machine using the PerformanceCounter.nextValue() method. The vast majority of these implementations consistently alternated values of either “0” or “100” on some machines and worked just fine on others, which is essentially worthless. And, since my apps tend to be deployed on many different types of machines, I needed something that worked all the time.
So, for a recent project I decided I was going to dig deep into Microsoft’s online documentation and solve this riddle once and for all. Sure enough I found what I was looking for in an article that mentioned using the System.Diagnostics. CounterSample Structure as a way to compare two PerformanceCounter values. That seemed like a perfect way to gaurantee better measurements.
So, here’s how I implemented it:
PerformanceCounter cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); CounterSample cs1 = cpuCounter.NextSample(); System.Threading.Thread.Sleep(100); CounterSample cs2 = cpuCounter.NextSample(); float finalCpuCounter = CounterSample.Calculate(cs1, cs2);
So why and how does this work? System.Diagnostics.CounterSample lets you compare two PerformanceCounter samples to come up with a float value. Rather than taking a snapshot value, which is what the nextValue() method does, you can compare values over a period of time. Here’s the official description from MSDN of the Calculate() method: “Calculates the performance data of the counter, using two sample points. This method is generally used for calculated performance counter types, such as averages.”
Feel free to experiment with adjusting the Thread.Sleep timeframe. It may need to be set slightly more or slightly less depending on the speed of the machine in which it runs, and the CPU activity on the machine. For example, if your machine activity is very sporadic and frantic, then you might want a shorter interval. Or, if you have long running processes that eat a fairly consistent amount of CPU you could probably lengthen the sleep time. I tested this pattern on a total of three different machines including two Windows 7 boxes and an 8-core, Windows Server 2008 box, and it worked very well.
Now, for those of you purists who hate seeing Thread.Sleep in any code there’s no need to yell at me. This is a sample for you to use as you see fit.