System.Diagnostics.PerformanceCounter and % Processor Time on multi-core or multi-cpu


While trying to build a task-manager type tool, I noticed that the idle task on my machine sometime consumed over 100% of the CPU!  160%, even 180%.  What’s going on?  I asked the base-class framework team and they’ve clued me in:


Process and Processor have different aggregation types.


 


·         “\Process(…)\% Processor Time” can go up to N*100 (where N is the number of CPUs) because it adds up the CPU usage of the requested process across all the CPUs.


·         “\Process(_Total)\% Processor Time” should always be around N*100 (where N is the number CPUs) because it adds up the CPU usage of each process, including the idle process.


·         “\Processor(…)\% Processor Time” can go up to 100 because it’s the CPU usage of the requested CPU.


·         “\Processor(_Total)\% Processor Time” can go up to 100 because it’s the average CPU usage across all CPUs.


In the above, Process(…) indicates a particular instance of the perf counter, pertaining to a particular process on the machine.  If you have a dual-core machine or a multi-cpu machine – these days even basic laptops have Core Duos – then you will see this behavior.  


Note: this assumes your code uses NextValue(), not NextSample.  Something like this:



    1     public class MyProcessInfo : INotifyPropertyChanged, IDisposable


    2     {


    3         System.Diagnostics.Process _p;


    4         System.Diagnostics.PerformanceCounter _perfCounter;


    5         public MyProcessInfo(System.Diagnostics.Process p)


    6         {


    7             _p = p;


    8             _Id = p.Id;


    9             _WorkingSetInKbytes = p.WorkingSet64 / 1024;


   10             _perfCounter =


   11                 new System.Diagnostics.PerformanceCounter(“Process”,


   12                     “% Processor Time”,


   13                     p.ProcessName,


   14                     true);


   15             _perfCounter.NextValue();


   16         }


   17 


   18         public void UpdateUtilization()


   19         {


   20             CpuUtilization = (int)(_perfCounter.NextValue());


   21         }


Keep in mind that you need to delay “about 1 second” between calls to NextValue(), as per the documentation!


 


Comments (1)

  1. zlx says:

    I think you made a type error, the correct should be:

    ·         “Processor(…)% Processor Time” can NOT go up to 100 because it’s the CPU usage of the requested CPU.

    ·         “Processor(_Total)% Processor Time” can NOT go up to 100 because it’s the average CPU usage across all CPUs.