Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Performance Counter or Process class correctly in C# to get memory usage of current process?

According to How to use .NET PerformanceCounter to track memory and CPU usage per process? PerformanceCounter should give me the number of memory usage of a given process.

According to MSDN, Process instance may also give me more or less the same number.

In order to verify my assumptions, I wrote the following code:

class Program
{
    static Process process = Process.GetCurrentProcess();

    static PerformanceCounter privateBytesCounter = new PerformanceCounter("Process", "Private Bytes", process.ProcessName);
    static PerformanceCounter workingSetCounter = new PerformanceCounter("Process", "Working Set", process.ProcessName);

    static void Main(string[] args)
    {


        GetMeasure();

        Console.WriteLine("\nPress enter to allocate great amount of memory");
        Console.ReadLine();
        int[] arr = new int[10000000];
        for (int i = 0; i < arr.Length; i++)
        {
            arr[i] = i;
        }

        GetMeasure();

        privateBytesCounter.Dispose();
        workingSetCounter.Dispose();
        Console.ReadKey();
    }

    private static void GetMeasure()
    {
        Console.WriteLine("{0,38} {1,20}", "Private bytes", "working set");
        Console.WriteLine("process data{0,23} {1,20}", process.PrivateMemorySize64 / 1024, process.WorkingSet64 / 1024);
        Console.WriteLine("PerformanceCounter data{0,12} {1,20}", privateBytesCounter.NextValue() / 1024, workingSetCounter.NextValue() / 1024);
    }

}

The output looks like

                         Private bytes          working set
process data                  22880                17516
PerformanceCounter data       21608                15608

Press enter to allocate great amount of memory

                         Private bytes          working set
process data                  22880                17516
PerformanceCounter data       21608                15608

Exactly the same! In the contrast, private bytes shown in Process Explorer increased from 32732 to 63620.

So am I doing something wrong?

like image 796
Gqqnbig Avatar asked Jan 23 '12 13:01

Gqqnbig


People also ask

How to use performance counter in c#?

To read from a performance counter, create an instance of the PerformanceCounter class, set the CategoryName, CounterName, and, optionally, the InstanceName or MachineName properties, and then call the NextValue method to take a performance counter reading.

How do I create a performance counter?

In the navigation pane, expand Monitoring Tools, and then choose Performance Monitor. In the console pane toolbar, choose the Add button. In the Add Counters window, in the Select counters from computer drop-down list, choose the computer that is running Business Central Server.

What are CPU performance counters?

The CPU performance counters are counting the number of instructions, clock ticks and multi counters ticks. They are used to measure the run-time of a c-function. The result is stored in a global variable.


2 Answers

You have to tell your process instance it should refresh its cached data. Data is not gathered each time you access to a property for performance purposes. You have to manually demand the data update.

private static void GetMeasure()
{
    process.Refresh();  // Updates process information

    Console.WriteLine("{0,38} {1,20}", "Private bytes", "working set");
    Console.WriteLine("process data{0,23} {1,20}", process.PrivateMemorySize64 / 1024, process.WorkingSet64 / 1024);
    Console.WriteLine("PerformanceCounter data{0,12} {1,20}", privateBytesCounter.NextValue() / 1024, workingSetCounter.NextValue() / 1024);
}

That's for your process. For performance counters, NextValue() is supposed to retrieve a new fresh data each time, so I can't explain why it doesn't on your machine. On mine it works fine.

EDIT:

With the process.Refresh() added, here's what I get:

                         Private bytes          working set
process data                  25596                22932
PerformanceCounter data       26172                23600

Press enter to allocate great amount of memory
                         Private bytes          working set
process data                  65704                61848
PerformanceCounter data       65828                61880
like image 116
ken2k Avatar answered Sep 19 '22 12:09

ken2k


Caution: my memory profiler (.NET Memory Profiler) revealed that Process.Refresh() allocates a significant chunk of memory on a temporary basis, so keep this in mind if you're reading your performance counters on a regular basis by using a timer.

like image 26
sevzas Avatar answered Sep 23 '22 12:09

sevzas