Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate private working set (memory)?

How do I calculate the private working set of memory using C#? I'm interested in producing roughly the same figures as taskmgr.exe.

I'm using the Process namespace and using methods/data like WorkingSet64 and PrivateMemorySize64, but these figures are off by 100MB or more at times.

like image 746
sholsapp Avatar asked Apr 09 '10 21:04

sholsapp


2 Answers

This is a highly variable number, you cannot calculate it. The Windows memory manager constantly swaps pages in and out of RAM. TaskMgr.exe gets it from a performance counter. You can get the same number like this:

using System;
using System.Diagnostics;

class Program {
    static void Main(string[] args) {
        string prcName = Process.GetCurrentProcess().ProcessName;
        var counter = new PerformanceCounter("Process", "Working Set - Private", prcName);
        Console.WriteLine("{0}K", counter.RawValue / 1024);
        Console.ReadLine();
    }
}

Do beware that the number really doesn't mean much, it will drop when other processes get started and compete for RAM.

like image 193
Hans Passant Avatar answered Nov 11 '22 18:11

Hans Passant


For future users, here is what I had to do to make sure to get the Private Working Set for processes that might have multiple instances. I call CurrentMemoryUsage, which gets the appropriate process name from GetNameToUseForMemory. I found this loop to be slow, even with filtering down the results where I could. So, that is why you see GetNameToUseForMemory using a dictionary for caching the name.

private static long CurrentMemoryUsage(Process proc)
{
  long currentMemoryUsage;
  var nameToUseForMemory = GetNameToUseForMemory(proc);
  using (var procPerfCounter = new PerformanceCounter("Process", "Working Set - Private", nameToUseForMemory))
  {
    //KB is standard
    currentMemoryUsage = procPerfCounter.RawValue/1024;
  }
  return currentMemoryUsage;
}

private static string GetNameToUseForMemory(Process proc)
{
  if (processId2MemoryProcessName.ContainsKey(proc.Id))
    return processId2MemoryProcessName[proc.Id];
  var nameToUseForMemory = String.Empty;
  var category = new PerformanceCounterCategory("Process");
  var instanceNames = category.GetInstanceNames().Where(x => x.Contains(proc.ProcessName));
  foreach (var instanceName in instanceNames)
  {
    using (var performanceCounter = new PerformanceCounter("Process", "ID Process", instanceName, true))
    {
      if (performanceCounter.RawValue != proc.Id) 
        continue;
      nameToUseForMemory = instanceName;
      break;
    }
  }
  if(!processId2MemoryProcessName.ContainsKey(proc.Id))
    processId2MemoryProcessName.Add(proc.Id, nameToUseForMemory);
  return nameToUseForMemory;
}
like image 43
Justin Pihony Avatar answered Nov 11 '22 17:11

Justin Pihony