0

I want implement a system that monitors currently running processes. The system get information about high load (CPU, Memory, etc.). I investigate two namespaces. It is System.Diagnostics and System.Management. First, I wrote a class to display the names, IDs and CPU Load of all running processes.

class Program
{
    static void Main()
    {
        Console.WriteLine("--------------using System.Diagnostics---------------------");
        SysDi();

        Console.WriteLine("----using System.Diagnostics CPU load always zero----------");

        //Here CPU load always zero
        SysDiCpuZero();

        Console.WriteLine("--------------using System.Management---------------------");
        Vmi();

    }


    static void Vmi()
    {
        try
        {
            var searcher = new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_PerfFormattedData_PerfProc_Process");

            foreach (var queryObj in searcher.Get())
            {
                Console.WriteLine($"Process: {queryObj["Name"]} " +
                                  $"ID: {queryObj["CreatingProcessID"]} " +
                                  $"CPU load: {queryObj["PercentProcessorTime"]}");
            }
        }
        catch (ManagementException e)
        {
            Console.WriteLine("An error occurred while querying for WMI data: " + e.Message);
        }
    }

    static void SysDi()
    {
        var processlist = Process.GetProcesses();
        var counters = new List<PerformanceCounter>();
        foreach (var theprocess in processlist)
        {
            var counter = new PerformanceCounter("Process", "% Processor Time", theprocess.ProcessName);

            counter.NextValue();
            counters.Add(counter);
        }

        var i = 0;


        Thread.Sleep(10);
        foreach (var counter in counters)
        {
            Console.WriteLine($"Process: {processlist[i].ProcessName} " +
                              $"ID: {processlist[i].Id} " +
                              $"CPU load: {Math.Round(counter.NextValue(), 5)}");
            ++i;
        }
    }

    static void SysDiCpuZero()
    {
        var processlist = Process.GetProcesses();

        foreach (var theprocess in processlist)
        {
            var counter = new PerformanceCounter("Process", "% Processor Time", theprocess.ProcessName);
            counter.NextValue();

            Console.WriteLine($"Process: {theprocess.ProcessName} " +
              $"ID: {theprocess.Id} " +
              $"CPU load: {Math.Round(counter.NextValue(), 5)}");
        }
    }
}

Also, I noticed that in different namespaces the same properties have different values. Also, System.Diagnostic faster than System.Management but method SysDi() with CPU loading data looks like unclear.

What is better to use in my case? What criteria should I follow to choose?

user6408649
  • 1,227
  • 3
  • 16
  • 40
  • 1
    Depending on your platform (Windows versions, etc.) and needs there are at least two more to consider: Performance Counters and ETW. – Christian.K Jun 23 '16 at 13:31
  • Hmya, the Process class isn't going to get you very far. What's better is so often determined by what's between the chair and the keyboard instead of a framework class. Using `SELECT *` when you actually only need `SELECT Name` is not better. These are both disposable classes but you don't dispose them. Use http://codereview.stackexchange.com/ if you need a code review. – Hans Passant Jun 23 '16 at 13:38
  • use ETW/xperf/WPR. – magicandre1981 Jun 23 '16 at 15:04

2 Answers2

1

Using your code and wrapping StopWatch's around it here is the result (ms):

WithWMI: 4ms 
WithoutWMI: 2ms

This is from just a single call, so using Process.GetProcess() is faster but it's also easier to read (In my opinion), you don't have to worry about magic strings (The query for example).

After running it a few times, it seems that using Process.GetProcess() is faster, in some runs they both take the same amount of time, but usually Process.GetProcess() is faster buy a few ms.

Also if you don't have to use WMI then don't, WMI is known to be slower.

Also it seems when querying the ManagementObjectSearcher it can use up more CPU compared to calling Process.GetProcess(), I noticed this by calling them both 10000 times and the WMIProvierHost was using up 50% CPU the whole way (I know this is not a normal use case calling the WMI Object 1000 times).

But the time difference between the two calls is really next to nothing, it all comes down to readability, and I would always use Process.GetProcess over querying WMI for the processes.

Jamie Rees
  • 7,973
  • 2
  • 45
  • 83
0

Use whatever is simpler and cleaner. In the future you might want expand functionality and your project might grow. The simplicity of initial step will pay off later on. WMI is meant to do everything possible but with a bit more overhead. For most cases Diagnostics is good enough though.

Timing considerations can play a role but I do not suppose you want to probe processes constantly so this should not be very important. Nevertheless, this aspect also points to Diagnostics.

Update

To get CPU load you can use PerformanceCounter class from Diagnostics namespace.

Community
  • 1
  • 1
Maciej
  • 7,871
  • 1
  • 31
  • 36