Search code examples
c#winformsprocesscpu-usage

Calculating process cpu usage from Process.TotalProcessorTime


I've been trying to move away from using the PerformanceCounter class for monitoring a process's CPU usage since it seems it requires a decent amount of CPU when the process count gets decently high (when monitoring a lot of processes).

My first approach was to take the WMI route using Win32_PerfFormattedData_PerfOS_Processor class and the PercentProcessorTime property, but there seems to be an issue when trying to calculate the CPU usage over multiple cores (the max value it's returning is 100% making it impossible to divide it based on the CPU core count, resulting in inaccurate results).

So finally I decided to use the Process's class TotalProcessorTime property. Sadly I am unsure how to calculate the percentage of the total CPU usage used by the Process based the value. I know that I should subtract the current PercentProcessorTime value from a previous PercentProcessorTime value to get how much time the processor spent on the process within a certain time limit but I am unsure how to continue from there.

Thanks in advance.


Solution

  • class GetCPUUsage
    {
        static TimeSpan start;
        public static double CPUUsageTotal
        {
            get;
            private set;
        }
    
        public static double CPUUsageLastMinute
        {
            get;
            private set;
        }
    
        static TimeSpan oldCPUTime = new TimeSpan(0);
        static DateTime lastMonitorTime = DateTime.UtcNow;
        public static DateTime StartTime = DateTime.UtcNow;
        // Call it once everything is ready
        static void OnStartup()
        {
            start = Process.GetCurrentProcess().TotalProcessorTime;
        }
    
        // Call this every 30 seconds
        static void CallCPU()
        {
            TimeSpan newCPUTime = Process.GetCurrentProcess().TotalProcessorTime - start;
            CPUUsageLastMinute = (newCPUTime - oldCPUTime).TotalSeconds / (Environment.ProcessorCount * DateTime.UtcNow.Subtract(lastMonitorTime).TotalSeconds);
            lastMonitorTime = DateTime.UtcNow;
            CPUUsageTotal = newCPUTime.TotalSeconds / (Environment.ProcessorCount * DateTime.UtcNow.Subtract(StartTime).TotalSeconds);
            oldCPUTime = newCPUTime;
        }
    }
    
    class GetCPUInfo
    {
        public static string GetInfoMinute()
        {
            return String.Format("{0:0.0}", GetCPUUsage.CPUUsageLastMinute * 100);
        }
    
        public static string GetInfoTotal()
        {
            return String.Format("{0:0.0}", GetCPUUsage.CPUUsageTotal * 100);
        }
    }