Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 642
coolmine Avatar asked Nov 03 '13 18:11

coolmine


People also ask

Can a process use more than 100% CPU?

%CPU -- CPU Usage : The percentage of your CPU that is being used by the process. By default, top displays this as a percentage of a single CPU. On multi-core systems, you can have percentages that are greater than 100%.

Can I limit CPU usage of a process?

The easiest solution I found is to limit Processor power. Go to Control Panel. Maximum processor state and lower it to 80% or whatever you want. Using software that measure CPU temperatures like 'Speed fan' you will see that temperatures drop.


2 Answers

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);
    }
}
like image 102
111WARLOCK111 Avatar answered Sep 22 '22 05:09

111WARLOCK111


Building upon 111WARLOCK111's answer, you can use the following minimal code to measure the current CPU load:

async Task<double> GetCpuLoadAsync(TimeSpan MeasurementWindow)
{
    Process CurrentProcess = Process.GetCurrentProcess();

    TimeSpan StartCpuTime = CurrentProcess.TotalProcessorTime;
    Stopwatch Timer = Stopwatch.StartNew();

    await Task.Delay(MeasurementWindow);

    TimeSpan EndCpuTime = CurrentProcess.TotalProcessorTime;
    Timer.Stop();

    return (EndCpuTime - StartCpuTime).TotalMilliseconds / (Environment.ProcessorCount * Timer.ElapsedMilliseconds);
}

Use the following code to call the function and replace the TimeSpan with the window to monitor:

double CpuLoad = await GetCpuLoadAsync(TimeSpan.FromSeconds(10));
like image 42
Simon Mattes Avatar answered Sep 22 '22 05:09

Simon Mattes