Share via


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 https://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());

    }

Comments

  • Anonymous
    June 05, 2006
    ...which explains the slight delay before the first value appears when you add a new counter in perfmon (this is best observed in the report view).

    I'm just playing around with the ASP.NET "Sessions Active" counter but it always seems to yield zero. Any ideas?

    I am not running through IIS and that's the only thing I can think of that might be stopping this from working.

    Here's the code-beside for my page:

    public partial class _Default : System.Web.UI.Page
    {
    private static readonly PerformanceCounter _performanceCounter = new PerformanceCounter("ASP.NET Apps v2.0.50727", "Sessions Active", "Total");

    protected void Page_Load(object sender, EventArgs e)
    {
    _label.Text = "Sessions: " + _performanceCounter.NextValue();
    }
    }

    Thanks,
    Kent
  • Anonymous
    June 06, 2006
    > "There is now way to determine how long it takes a provider of a counter to update it’s values but ..."

    That should read "This is no way (etc)", correct?

    (Alternately, it could be "There is now a way....")
  • Anonymous
    June 22, 2006
    I’ve seen this question come up a few times and the solution is hard to infer, especially given that...
  • Anonymous
    June 08, 2009
    PingBack from http://insomniacuresite.info/story.php?id=7630