How to Read Performance Counters [Ryan Byington]

In the time that I have owned performance counters I have seen a lot of code that incorrectly uses the PerformanceCounter class to read counter values. This entry seeks to explain the proper way to read counter values using the PerformanceCounter class.

 

Reading performance counters is not as trivial as you might think. You can't simple “new” one up, call NextValue on it, and expect it to return the proper value. For example the following code attempts to display the total processor time however it will likely always just display 0.

    PerformanceCounter totalProcessorTimeCounter = new PerformanceCounter(

         “Process”,

         “% Processor Time”,

         “_Total”);

    Console.WriteLine(totalProcessorTimeCounter.NextValue());

 

The problem with the above code is that most counters need two samples to perform the calculation. The calulations are generally something like (currentSampleValue – previousSampleValue) / (currentSampleTime – previousSampleTime). See http://msdn2.microsoft.com/en-us/system.diagnostics.performancecountertype.aspx for a complete description of the all of the different counter types and calculations. The first time NextValue is called the PerformanceCounter class only has one sample and it uses 0 for the values of the previous sample causing the calculation to be way off.

 

So you are probably thinking all you have to do is call NextValue twice to get it to return the correct value for the counter. Unfortunately this is not the case. If you call NextValue twice without waiting between the calls, the previous sample value and the current sample value will likely be the same value, so NextValue will likely return 0 (depending on the counter type). The problem is that the provider of the counter (the operating system for the Processor category) may update the value of the counter only once per second. You will have to wait for the provider to update the counter sample value in between calls to NextValue. There is no way to determine how long it takes a provider of a counter to update it’s values but waiting a second is sufficient for most counters.

The following is the correct code to get the counter value:

    PerformanceCounter totalProcessorTimeCounter = new PerformanceCounter(

         “Process”,

         “% Processor Time”,

         “_Total”);

    totalProcessorTimeCounter.NextValue();

    System.Threading.Thread.Sleep(1000);// 1 second wait

    Console.WriteLine(totalProcessorTimeCounter.NextValue());

If you are monitoring multiple counters you do not have to wait one second in between every call to NextValue. You only have to ensure that at least one second has elapsed since the last time you called NextValue on that specific counter. So you can just wait one second in between each time you gather all of the values for the counters being monitored like the following code:

    System.Collections.Generic.List<PerformanceCounter> counters =

        new System.Collections.Generic.List<PerformanceCounter>();

    foreach (Process process in Process.GetProcesses()) {

        PerformanceCounter processorTimeCounter = new PerformanceCounter(

        "Process",

        "% Processor Time",

        process.ProcessName);

        processorTimeCounter.NextValue();

        counters.Add(processorTimeCounter);

    }

    System.Threading.Thread.Sleep(1000); // 1 second wait

    foreach(PerformanceCounter processorTimeCounter in counters) {

        Console.WriteLine(

            "Process:{0} CPU% {1}",

            processorTimeCounter.InstanceName,

            processorTimeCounter.NextValue());

    }