10

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.

Vinyl Warmth
  • 2,226
  • 3
  • 25
  • 50
sholsapp
  • 165
  • 2
  • 2
  • 7

2 Answers2

33

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 2
    How do you mean that, "the number really doesn't mean much"? Doesn't this figure represent how much memory the process uses that cannot be shared with another process? I'm interested in building a service that will kill process "abusive" processes - "abusive" being defined as processes using more than x many MB of memory. I would hate to write the service if the figure I'm using really doesn't mean much. What would you suggest? – sholsapp Apr 09 '10 at 23:15
  • 1
    No, that's not what the number means. You are looking for "Private Bytes", the amount of *virtual* memory taken by a process that can't be shared by other processes. – Hans Passant Apr 09 '10 at 23:57
  • 12
    While all being said is correct, I wanted to add, that just using the `ProcessName` to lookup the matching counter instance is not enough. If you have multiple processes with the same (e.g. svchost.exe) then the counter names will be "svchost#1", "svchost#2", etc. You need to match via the "ID Process" counter, which is also part of the process category, and `Process.ID`. – Christian.K Sep 21 '10 at 07:12
1

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;
}
Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
  • 1
    Note that caching the value won't work, as "older" process might shutdown and the instanceName gets "re-keyed" http://blogs.technet.com/b/askperf/archive/2010/03/30/perfmon-identifying-processes-by-pid-instead-of-instance.aspx – Andre Apr 09 '13 at 19:52
  • broken link : updated here https://techcommunity.microsoft.com/t5/ask-the-performance-team/perfmon-identifying-processes-by-pid-instead-of-instance/ba-p/374561 – norisknofun Apr 07 '20 at 09:58