8

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?

Community
  • 1
  • 1
Gqqnbig
  • 5,845
  • 10
  • 45
  • 86

2 Answers2

9

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
ken2k
  • 48,145
  • 10
  • 116
  • 176
  • Are the values given by the two exactly the same or not? Can you post them? I want to have a look. – Gqqnbig Jan 23 '12 at 15:24
  • 1
    It's strange that now even without refresh method my PerformanceCounter can give the correct number.... BTW, you refresh method works fine. Thanks. – Gqqnbig Jan 23 '12 at 15:34
4

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.

sevzas
  • 701
  • 2
  • 5
  • 13