Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting a CPU usage of 0% all the time?

Tags:

c#

.net

winforms

This is what im doing in form1:

void PopulateApplications()
{
    DoubleBufferedd(dataGridView1, true);

    int rcount = dataGridView1.Rows.Count;
    int rcurIndex = 0;

    foreach (Process p in Process.GetProcesses())
    {
        try
        {
            if (File.Exists(p.MainModule.FileName))
            {
                memoryUsage = Core.getallmemoryusage(p.ProcessName);
                Core.getcpu(p.ProcessName);
                cpuusage = Core.processes;

                var icon = Icon.ExtractAssociatedIcon(p.MainModule.FileName);
                Image ima = icon.ToBitmap();
                ima = resizeImage(ima, new Size(25, 25));
                ima = (Image)(new Bitmap(ima, new Size(25, 25)));
                String status = p.Responding ? "Running" : "Not Responding";

                if (rcurIndex < rcount - 1)
                {
                    var currentRow = dataGridView1.Rows[rcurIndex];
                    currentRow.Cells[0].Value = ima;
                    currentRow.Cells[1].Value = p.ProcessName;
                    currentRow.Cells[2].Value = cpuusage;
                    currentRow.Cells[3].Value = memoryUsage;
                    currentRow.Cells[4].Value = status;
                }
                else
                {
                    dataGridView1.Rows.Add(ima, p.ProcessName,cpuusage,memoryUsage, status);//false, ima, p.ProcessName, status);
                }

                rcurIndex++;
            }
        }
        catch ( Exception e)
        {
            string t = "error";
        }
    }

    if (rcurIndex < rcount - 1)
    {
        for (int i = rcurIndex; i < rcount - 1; i++)
        {
            dataGridView1.Rows.RemoveAt(rcurIndex);
        }
    }
}

Now the method in form1 PopulateApplications, I call it from a timer tick event each 5 seconds. Then I loop each time over the processes and get the memory usage and CPU usage. This are the methods of memory and CPU in the class Core.

With the memory method there is no problems. Working good and fast.

public static string getallmemoryusage(string processName)
{
    var counter = new PerformanceCounter("Process", "Working Set - Private", processName);
    privateMemeory = (counter.NextValue() / 1024 / 1024).ToString();
    //string.Format("Private memory: {0}k", counter.NextValue() / 1024 / 1024);
    return privateMemeory;           
}

The problem is with the getcpu method. I need to make it sleep every 1000ms few times to get the CPU usage. If I use a breakpoint on this method, I will get the value in the end. The problem is when I call the method in form1 each 5 seconds it's also calling and doing this getcpu every 5 seconds and those threads sleep make it work very slow. If I will set the threads sleep to 10ms it will be faster but then I get on most processes 0% or 100% usage.

public static string  getcpu(string name)
{
    var cpuload = new PerformanceCounter("Processor", "% Processor Time", "_Total");

    processes = Convert.ToInt32(cpuload.NextValue()) + "%";
    System.Threading.Thread.Sleep(1000);

    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);

    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);

    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);

    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);

    return processes;
}
like image 344
user3681442 Avatar asked Jun 09 '14 14:06

user3681442


1 Answers

When measuring % Processor Time, the Thread.Sleep(1000) is required since the .NextValue() call determines the time, the processor was used since the last call to .NextValue(). For further information on this calculation, check out http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx.

A couple of suggestions:

1) Since you are passing in the name of a process, I assume you want to measure the Processor Time of a single process. But as you are not using that parameter within your method, you are measuring the overall average system processor time instead.

So if you want to measure the performance for one single process, you could use something like:

public static double GetCpuUsage(Process process)
{
    PerformanceCounter cpuCounter = new PerformanceCounter();

    cpuCounter.CategoryName = "Process";
    cpuCounter.InstanceName = process.ProcessName;
    cpuCounter.CounterName = "% Processor Time";

    // The first call will always return 0
    cpuCounter.NextValue();
    // That's why we need to sleep 1 second 
    Thread.Sleep(1000);
    // The second call determines, the % of time that the monitored process uses on 
    // % User time for a single processor. 
    // So the limit is 100% * the number of processors you have.
    double processorUsagePercent = cpuCounter.NextValue();

    // Hence we need to divide by the number of processors to get the average CPU usage of one process during the time measured
    return processorUsagePercent / Environment.ProcessorCount;
}

Please mind the difference between "Processor" and "Process" for the counter category.

2) Why are you calling .NextValue() multiple times in a row and then return only the last value? That makes your method so slow. The two calculations shown in the example above are sufficient.

3) When you want to monitor multiple processes, you do not have to wait one second in between every call to .NextValue(). You just have to make sure that at least one second has elapsed since the last time you called .NextValue() on a specific counter. So for multiple processes you could have a method like that:

public static Dictionary<Process, double> GetCpuUsages(Process[] processes)
{
    // One performance counter is required per process
    PerformanceCounter[] counters = new PerformanceCounter[processes.Length];

    // Instantiate a new counter per process
    for(int i = 0; i < processes.Length; i++)
    {
        PerformanceCounter processorTimeCounter = new PerformanceCounter(
            "Process",
            "% Processor Time",
            processes[i].ProcessName);
        // Call NextValue once to have a reference value
        processorTimeCounter.NextValue();
        // Add it to the array
        counters[i] = processorTimeCounter;
    }

    // Sleep one second to have accurate measurement
    Thread.Sleep(1000); 
    // Here we store the processes along with their measurement in a dictionary
    Dictionary<Process, double> cpuUsageDictionary = new Dictionary<Process, double>();

    for (int i = 0; i < counters.Length; i++)
    {
        // Determine CPU usage and divide by the number of cores
        double cpuUsage = counters[i].NextValue() / Environment.ProcessorCount;
        // And now we add one key/value pair per process along with its cpu time measurement
        cpuUsageDictionary.Add(processes[i],  cpuUsage);
    }

    return cpuUsageDictionary;
}
like image 51
Ben Sch Avatar answered Oct 09 '22 20:10

Ben Sch