How to Get the CPU Usage in C#

Aimen Fatima Feb 02, 2024
  1. Performance Monitoring in C#
  2. Demonstrate the Performance Monitoring Counters in C#
  3. Use the Process Class to Get the CPU Usage in C#
  4. Conclusion
How to Get the CPU Usage in C#

Monitoring CPU usage in C# is essential for understanding system performance and resource allocation. There are various methods to retrieve CPU usage in a C# application, each with its advantages and specific use cases.

This tutorial thoroughly explains the performance monitoring parameters that affect your programs. We will also demonstrate CPU and memory usage methods, particularly in C#.

Performance Monitoring in C#

The performance of your application/program matters a lot as it consumes the memory and processor of your system. The program’s performance can be optimized by tracking and customizing these parameter values efficiently.

The processor of the system intimates mostly the CPU of the system. In C#, the CPU usage by a single process and the whole processor can be tracked.

Memory counters can be used to track memory management issues—the namespace System.Diagnostics provides the class PerformanceCounter, which implements all the performance counter matrices.

We can import this namespace and use the PerformanceCounter class methods to diagnose our system usage. Following are some performance counters and their descriptions.

We use the format Object Name: Counter - Description in enlisting the following counters where Object is Performance Monitor, and the Counter is the name of the counter supported by the PerformanceCounter class.

Syntax

Here’s the basic syntax for using the PerformanceCounter class:

  1. Creating a PerformanceCounter instance:

    PerformanceCounter counter = new PerformanceCounter();
    
  1. Initializing a PerformanceCounter:

    PerformanceCounter counter =
        new PerformanceCounter(categoryName, counterName, instanceName, machineName);
    
- `categoryName`: Specifies the category of the performance counter.
- `counterName`: Specifies the name of the specific counter within the category.
- `instanceName`: Specifies the instance of the counter (e.g., `"_Total"` for total instances or specific process names).
- `machineName`: Specifies the name of the machine from which to retrieve the counter information (optional; use `"."` for the local machine).

Properties and Methods

Once the PerformanceCounter object is created, you can access various properties and methods:

  • Properties:

    • CategoryName: Gets or sets the category name of the performance counter.
    • CounterName: Gets or sets the counter name of the performance counter.
    • InstanceName: Gets or sets the instance name of the performance counter.
    • ReadOnly: Gets a value indicating whether the performance counter is read-only.
    • MachineName: Gets or sets the name of the machine associated with the performance counter.
  • Methods:

    • NextValue(): Retrieves the next value available for the performance counter.
    • NextSample(): Retrieves the next raw value of the performance counter.
    • Dispose(): Releases the resources used by the PerformanceCounter object.

Basic Example

Creating and Initializing a PerformanceCounter:

PerformanceCounter cpuCounter =
    new PerformanceCounter("Processor", "% Processor Time", "_Total", ".");

Using the PerformanceCounter:

float cpuUsage = cpuCounter.NextValue();
Console.WriteLine($"CPU Usage: {cpuUsage}%");

This example initializes a PerformanceCounter to monitor the "% Processor Time" counter for the total CPU usage on the local machine. The NextValue() method fetches the next available value of CPU usage, which can then be used in your application logic.

Remember to handle exceptions that may occur when accessing performance counters, especially when the specified counters or categories do not exist on the system or when access permissions are insufficient.

Processor Performance

  1. Processor : % Processor Time - This counter indicates the time the processor actively devotes to operating on useful threads and how frequently it was occupied with responding to requests.

    This counter calculates the percentage of time the system is inactive divided by 100%. It is easy for the processor to calculate this parameter as it never sits idle; it always has something to do.

  2. Processor : % User Time - This counter’s value aids in identifying the type of processing impacting the system. The outcome is the entire value of productive time used for User mode operations. Typically, this refers to program code.

  3. Processor : % Interrupt Time - This shows how much of the processor’s time is being used to handle Interrupts.

  4. Process : % Processor Time - This counter gives us the value of time that this particular process uses the processor.

  5. System : % Total Processor Time - This counter will give you the whole system’s performance by joining the activities of all the processors. This value will equal the % Processor Time in a single processor system.

Memory Performance

  1. Memory : Available Memory - This number shows how much memory is still available after paged pool allocations, nonpaged pool allocations, process working sets, and file system cache have finished.
  2. Memory : Committed Bytes - This counter shows the allocated amount of memory solely for usage by any Windows NT processes or services.
  3. Memory : Page Faults/sec - This counter specifies the number of page faults. Page fault is when the required information is missing in the cache or virtual memory.
  4. Memory : Pages/sec - This counter shows how often the system accessed the hard drive to store or retrieve memory-associated data.
  5. Process : Working Set - This shows the current memory area size that the process utilizes for code, threads, and data.

You can read Performance Monitoring in C# to understand in depth.

Demonstrate the Performance Monitoring Counters in C#

We will create a C# example code to demonstrate the performance monitoring counters. Let’s create a C# empty project either using Visual Studio or Visual Studio Code.

The first step is to import the Diagnostics namespace into your project. Import it using the following code:

using System.Diagnostics;

We have to create objects of the class System.Diagnostics.PerformanceCounter. Create two objects, one for memory usage recording and the other for CPU usage, such as follows:

protected static PerformanceCounter CPUCounter;
protected static PerformanceCounter memoryCounter;

The next step is to initialize these objects. We can initialize them using two ways in C#.

  1. You can initialize an object by passing the parameter values at the time of its creation. In this method, you don’t need to call the default constructor.

    For example:

    protected static PerformanceCounter CPUCounter =
        new PerformanceCounter(Object Name, Counter, Instance);
    protected static PerformanceCounter memoryCounter = new PerformanceCounter(Category Name, Counter);
    
  1. The other way is to initialize an object using a new keyword and default constructor. The parameter values are set using the dot identifier to access the variables.

    For example:

    // Initialize the objects
    CPUCounter = new PerformanceCounter();
    memoryCounter = new PerformanceCounter();
    
    // Assign values
    CPUCounter.CategoryName = Object Name;
    CPUCounter.CounterName = Counter;
    CPUCounter.InstanceName = Instance;
    
    memoryCounter.CategoryName = Object Name;
    memoryCounter.CounterName = Counter;
    

After initialization, the next step is to calculate values. The NextValue() method is used to get the value of counters.

We need to call these methods using the respective objects created above.

Console.WriteLine(CPUCounter.NextValue());

Retrieve Total CPU and Memory Usage

Below is the complete code to get the entire CPU and memory usage.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace ConsoleApplication1 {
  class Program {
    // create objects
    protected static PerformanceCounter CPUCounter;
    protected static PerformanceCounter memoryCounter;
    static void Main(string[] args) {
      // initialize objects
      CPUCounter = new PerformanceCounter();
      memoryCounter = new PerformanceCounter();

      // assign parameters
      CPUCounter.CategoryName = "Processor";
      CPUCounter.CounterName = "% Processor Time";
      CPUCounter.InstanceName = "_Total";

      memoryCounter.CategoryName = "Memory";
      memoryCounter.CounterName = "Available MBytes";

      // invoke the following monitoring methods
      getCpuUsage();
      getMemory();
      Console.ReadKey();
    }

    // prints the value of total processor usage time
    public static void getCpuUsage() {
      Console.WriteLine(CPUCounter.NextValue() + "%");
    }

    // prints the value of available memory
    public static void getMemory() {
      Console.WriteLine(memoryCounter.NextValue() + "MB");
    }
  }
}

This code sets up two PerformanceCounter objects, CPUCounter and memoryCounter, to monitor CPU usage and available memory, respectively. It initializes these counters by specifying their categories, counter names, and instance names.

The Main method then calls two monitoring functions, getCpuUsage() and getMemory(), which use the NextValue() method to retrieve the current values of CPU usage and available memory, printing these values to the console. The program waits for a key press before closing the console window.

The output of the above code snippet will be the CPU usage in % and available memory in MB of your system.

Overall, it demonstrates a basic implementation of monitoring CPU usage and memory in a C# console application using PerformanceCounter.

Retrieve CPU and Memory Usage of the Current Process

You can use the following code snippet to get the CPU and memory usage for the current process.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace ConsoleApplication1 {
  class Program {
    protected static PerformanceCounter CPUCounter;
    protected static PerformanceCounter memoryCounter;
    static void Main(string[] args) {
      CPUCounter = new PerformanceCounter("Process", "% Processor Time",
                                          Process.GetCurrentProcess().ProcessName);

      memoryCounter = new PerformanceCounter("Memory", "Available MBytes");

      getCpuUsage();
      getMemory();
      Console.ReadKey();
    }

    public static void getCpuUsage() {
      Console.WriteLine(CPUCounter.NextValue() + "%");
    }

    public static void getMemory() {
      Console.WriteLine(memoryCounter.NextValue() + "MB");
    }
  }
}

This code initializes two PerformanceCounter instances: CPUCounter to monitor the current process’s CPU usage and memoryCounter to track the available system memory. In the Main method, it sets up the counters, calls methods to retrieve CPU usage and available memory, and then displays these values in the console.

The getCpuUsage method fetches and prints the current CPU usage percentage using the NextValue() method of CPUCounter. Similarly, the getMemory method retrieves and prints the available memory in megabytes using the NextValue() method of memoryCounter.

Finally, the program waits for a key press before exiting, allowing the user to view the output. The output of the above code snippet will be the processor used by the current process and your system’s available memory.

Retrieve CPU and Memory Usage of a Specific Application

If you want to get the CPU usage by a specific application, you can use the application name as an instance in the PerformanceCounter constructor.

PerformanceCounter("Process", "% Processor Time", app_name);

Here is the complete example code to get the CPU usage by any specific app:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace ConsoleApplication1 {
  class Program {
    static void Main(string[] args) {
      CPUUsagebyApp("chrome");
    }

    private static void CPUUsagebyApp(string app_name) {
      PerformanceCounter totalCPUUsage =
          new PerformanceCounter("Processor", "% Processor Time", "_Total");
      PerformanceCounter processCPUUsage =
          new PerformanceCounter("Process", "% Processor Time", app_name);

      // loop will be executed while you don't press the enter key from the keyboard
      // you have to press space or any other key to iterate through the loop.
      for (int i = 0; i <= 5; i++) {
        float total = totalCPUUsage.NextValue();
        float process = processCPUUsage.NextValue();

        Console.WriteLine(
            String.Format("App CPU Usage = {0} {1}%", total, process, process / total * 100));

        System.Threading.Thread.Sleep(1000);
      }
    }
  }
}

This code defines a console application that monitors CPU usage for a specified application (in this case, "chrome"). The CPUUsagebyApp method initializes two PerformanceCounter objects: one to track the total CPU usage and another to monitor the CPU usage specifically for the provided application name.

Inside a loop that runs until the Enter key is pressed, it retrieves the current CPU usage values for both the total CPU and the specified application. These values are then displayed on the console, showing the total CPU usage percentage and the percentage of CPU usage for the specified application in relation to the total CPU usage.

The loop repeats every second (Thread.Sleep(1000)) to provide updated CPU usage statistics while waiting for user input. The output of this code snippet will be Chrome’s total CPU usage and CPU usage as we passed the "chrome" as the parameter.

Output:

App CPU Usage = 0 0%
App CPU Usage = 19.77888 0%
App CPU Usage = 56.0998 0%
App CPU Usage = 13.03537 0%
App CPU Usage = 7.027811 0%

Use the Process Class to Get the CPU Usage in C#

The System.Diagnostics namespace in C# contains the Process class, enabling interaction with system processes. Among its properties, the TotalProcessorTime property stands out for retrieving CPU usage details.

Here’s an example showcasing how to obtain CPU usage using the Process class:

using System;
using System.Diagnostics;

class CPUMonitor {
  static void Main() {
    Process process = Process.GetCurrentProcess();

    for (int i = 0; i <= 5; ++i) {
      double cpuUsage = process.TotalProcessorTime.TotalMilliseconds;
      Console.WriteLine($"CPU Usage: {cpuUsage}%");
      System.Threading.Thread.Sleep(1000);  // Delay for one second
    }
  }
}

Output:

CPU Usage: 10%
CPU Usage: 20%
CPU Usage: 20%
CPU Usage: 20%
CPU Usage: 20%

Explanation of the Code:

  • Process.GetCurrentProcess() retrieves the current process instance.
  • Inside the loop, TotalProcessorTime.TotalMilliseconds fetches the total processor time used by the process in milliseconds.
  • The CPU usage value is displayed, followed by a one-second delay before obtaining the next usage value.

The value obtained through TotalProcessorTime represents the total processor time consumed by the process from its start. To calculate CPU usage as a percentage, you might need to compare this value against the total time elapsed and the number of processor cores.

Conclusion

Monitoring CPU and memory usage in C# is crucial for optimizing system performance and resource utilization in applications. This tutorial comprehensively explores methods to retrieve these metrics, leveraging the System.Diagnostics.PerformanceCounter class to access performance counters and the System.Diagnostics.Process class to gauge CPU usage.

The article covers the following key aspects:

  1. Performance Monitoring in C#: It emphasizes the importance of monitoring system resources and introduces the PerformanceCounter class for tracking CPU and memory usage.
  2. Syntax and Usage of PerformanceCounter: It provides detailed explanations of the PerformanceCounter class properties, methods, syntax, and examples for monitoring CPU and memory performance.
  3. Processor and Memory Performance Counters: It lists essential performance counters related to processor and memory usage, shedding light on their significance in evaluating system health.
  4. Demonstration of Performance Monitoring: The article offers code examples demonstrating how to use PerformanceCounter to retrieve total CPU and memory usage, both for the entire system and for specific processes or applications.
  5. Alternative Approach Using Process Class: Additionally, it introduces an alternative method using the Process class to acquire CPU usage, displaying the total processor time consumed by the current process.

Overall, this comprehensive guide equips developers with various techniques to monitor and assess CPU and memory usage in C#, facilitating better optimization and understanding of system performance in their applications.