traveler3468
traveler3468

Reputation: 1681

Trying To Pull CPU & Network Usage Information From Performance Monitor

I'm trying to get CPU and network usage information from a process.
In my example, I will use the process chrome

Here is how im calling the method using an IEnumerable<String>

foreach (string p in GetProcessStatistics(new string[] { "chrome" }))
{
  Console.WriteLine(p);
}

And here is the method.

    private static IEnumerable<String> GetProcessStatistics(String[] processesTosearch)
    {
        Process[] processList = Process.GetProcesses();

        foreach (string process in processesTosearch)
        {
            foreach (Process p in processList)
            {
                if (p.ProcessName == process)
                {
                    StringBuilder sb = new StringBuilder();
                    PerformanceCounter CPUperformanceCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
                    double cpuData = CPUperformanceCounter.NextValue();
                    PerformanceCounter NETWORKperformanceCounter = new PerformanceCounter("Process", "IO Data Operations/Sec", p.ProcessName);
                    double networkData = NETWORKperformanceCounter.NextValue();

                    sb.AppendLine("ID: " + p.Id.ToString());
                    sb.AppendLine("NAME: " + p.ProcessName);
                    sb.AppendLine("CPU USAGE: " + cpuData);
                    sb.AppendLine("RAM USAGE: " + ConvertToReadableSize(p.PrivateMemorySize64));
                    sb.AppendLine("NETWORK USAGE: " + networkData);
                    yield return sb.ToString();
                }
            }
        }
    }

And here is the output of one of the results

ID: 17624
NAME: chrome
CPU USAGE: 0
RAM USAGE: 23.2MB
NETWORK USAGE: 0

When I look at Performance Monitor, the cpu and network values are not 0, however in the console, they are.

I understand from some research that the values will never be perfect, but why are they showing 0 in the console application and not on performance monitor?

Upvotes: 2

Views: 477

Answers (2)

Alan
Alan

Reputation: 2086

I like Jeff's solution, but for me I wanted an average. There were a couple problems getting CPU utilization that seemed like there should be an easy package to solve but I didn't see one.

The first is of course that a value of 0 on the first request is useless. Since you already know that the first response is 0, why doesn't the function just take that into account and return the true .NextValue()?

The second problem is that an instantaneous reading may be wildly inacurrate when trying to make decisions on what resources your app may have available to it since it could be spiking, or between spikes.

My solution was to do a for loop that cycles through and gives you an average for the past few seconds. you can adjust the counter to make it shorter or longer (as long as it is more than 2).

public static float ProcessorUtilization;

public static float GetAverageCPU()
{
    PerformanceCounter cpuCounter = new PerformanceCounter("Process", "% Processor Time", Process.GetCurrentProcess().ProcessName);
    for (int i = 0; i < 11; ++i)
    {
        ProcessorUtilization += (cpuCounter.NextValue() / Environment.ProcessorCount);
    }
    // Remember the first value is 0, so we don't want to average that in.
    Console.Writeline(ProcessorUtilization / 10); 
    return ProcessorUtilization / 10;
}

Upvotes: 1

Jeff Mercado
Jeff Mercado

Reputation: 134591

You'll need at least two reads for every counter, at least a second apart to get a usable reading.

Rearrange as needed but you would need to do something like this:

private static IEnumerable<String> GetProcessStatistics(String[] processesTosearch)
{
    Process[] processList = Process.GetProcesses();

    foreach (string process in processesTosearch)
    {
        foreach (Process p in processList)
        {
            if (p.ProcessName == process)
            {
                StringBuilder sb = new StringBuilder();
                PerformanceCounter CPUperformanceCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
                PerformanceCounter NETWORKperformanceCounter = new PerformanceCounter("Process", "IO Data Operations/Sec", p.ProcessName);

                // set a baseline
                CPUperformanceCounter.NextValue();
                NETWORKperformanceCounter.NextValue();

                Thread.Sleep(1000);

                double cpuData = CPUperformanceCounter.NextValue();
                double networkData = NETWORKperformanceCounter.NextValue();

                sb.AppendLine("ID: " + p.Id.ToString());
                sb.AppendLine("NAME: " + p.ProcessName);
                sb.AppendLine("CPU USAGE: " + cpuData);
                sb.AppendLine("RAM USAGE: " + ConvertToReadableSize(p.PrivateMemorySize64));
                sb.AppendLine("NETWORK USAGE: " + networkData);
                yield return sb.ToString();
            }
        }
    }
}

Upvotes: 2

Related Questions