Process Memory Size - Different Counters

16,761

Solution 1

If you want to know how much the GC uses try:

GC.GetTotalMemory(true)

If you want to know what your process uses from Windows (VM Size column in TaskManager) try:

Process.GetCurrentProcess().PrivateMemorySize64

If you want to know what your process has in RAM (as opposed to in the pagefile) (Mem Usage column in TaskManager) try:

Process.GetCurrentProcess().WorkingSet64

See here for more explanation on the different sorts of memory.

Solution 2

OK, I found through Google the same page that Lars mentioned, and I believe it's a great explanation for people that don't quite know how memory works (like me).

http://shsc.info/WindowsMemoryManagement

My short conclusion was:

  • Private Bytes = The Memory my process has requested to store data. Some of it may be paged to disk or not. This is the information I was looking for.

  • Virtual Bytes = The Private Bytes, plus the space shared with other processes for loaded DLLs, etc.

  • Working Set = The portion of ALL the memory of my process that has not been paged to disk. So the amount paged to disk should be (Virtual - Working Set).

Thanks all for your help!

Solution 3

If you want to use the "Memory (Private Working Set)" as shown in Windows Vista task manager, which is the equivalent of Process Explorer "WS Private Bytes", here is the code. Probably best to throw this infinite loop in a thread/background task for real-time stats.

using System.Threading;
using System.Diagnostics;

//namespace...class...method

Process thisProc = Process.GetCurrentProcess();
PerformanceCounter PC = new PerformanceCounter();

PC.CategoryName = "Process";
PC.CounterName = "Working Set - Private";
PC.InstanceName = thisProc.ProcessName;

while (true)
{
 String privMemory = (PC.NextValue()/1000).ToString()+"KB (Private Bytes)";
 //Do something with string privMemory

 Thread.Sleep(1000);
}

Solution 4

To get the value that Task Manager gives, my hat's off to Mike Regan's solution above. However, one change: it is not: perfCounter.NextValue()/1000; but perfCounter.NextValue()/1024; (i.e. a real kilobyte). This gives the exact value you see in Task Manager.

Following is a full solution for displaying the 'memory usage' (Task manager's, as given) in a simple way in your WPF or WinForms app (in this case, simply in the title). Just call this method within the new Window constructor:

    private void DisplayMemoryUsageInTitleAsync()
    {
        origWindowTitle = this.Title; // set WinForms or WPF Window Title to field
        BackgroundWorker wrkr = new BackgroundWorker();
        wrkr.WorkerReportsProgress = true;

        wrkr.DoWork += (object sender, DoWorkEventArgs e) => {
            Process currProcess = Process.GetCurrentProcess();
            PerformanceCounter perfCntr = new PerformanceCounter();
            perfCntr.CategoryName = "Process";
            perfCntr.CounterName = "Working Set - Private";
            perfCntr.InstanceName = currProcess.ProcessName;

            while (true)
            {
                int value = (int)perfCntr.NextValue() / 1024;
                string privateMemoryStr = value.ToString("n0") + "KB [Private Bytes]";
                wrkr.ReportProgress(0, privateMemoryStr);
                Thread.Sleep(1000);
            }
        };

        wrkr.ProgressChanged += (object sender, ProgressChangedEventArgs e) => {
            string val = e.UserState as string;
            if (!string.IsNullOrEmpty(val))
                this.Title = string.Format(@"{0}   ({1})", origWindowTitle, val);
        };

        wrkr.RunWorkerAsync();
    }`

Solution 5

Is this a fair description? I'd like to share this with my team so please let me know if it is incorrect (or incomplete):

There are several ways in C# to ask how much memory my process is using.

  • Allocated memory can be managed (by the CLR) or unmanaged.
  • Allocated memory can be virtual (stored on disk) or loaded (into RAM pages)
  • Allocated memory can be private (used only by the process) or shared (e.g. belonging to a DLL that other processes are referencing).

Given the above, here are some ways to measure memory usage in C#:

1) Process.VirtualMemorySize64(): returns all the memory used by a process - managed or unmanaged, virtual or loaded, private or shared.

2) Process.PrivateMemorySize64(): returns all the private memory used by a process - managed or unmanaged, virtual or loaded.

3) Process.WorkingSet64(): returns all the private, loaded memory used by a process - managed or unmanaged

4) GC.GetTotalMemory(): returns the amount of managed memory being watched by the garbage collector.

Share:
16,761
recursive9
Author by

recursive9

Founder of Crystal Gears Portfolio: - www.movertrends.com - www.friendshopper.com - www.digitalshow.com - www.translatorscorner.com - www.gigpay.com

Updated on June 07, 2022

Comments

  • recursive9
    recursive9 almost 2 years

    I'm trying to find out how much memory my own .Net server process is using (for monitoring and logging purposes).

    I'm using:

    Process.GetCurrentProcess().PrivateMemorySize64
    

    However, the Process object has several different properties that let me read the memory space used: Paged, NonPaged, PagedSystem, NonPagedSystem, Private, Virtual, WorkingSet

    and then the "peaks": which i'm guessing just store the maximum values these last ones ever took.

    Reading through the MSDN definition of each property hasn't proved too helpful for me. I have to admit my knowledge regarding how memory is managed (as far as paging and virtual goes) is very limited.

    So my question is obviously "which one should I use?", and I know the answer is "it depends".

    This process will basically hold a bunch of lists in memory of things that are going on, while other processes communicate with it and query it for stuff. I'm expecting the server where this will run on to require lots of RAM, and so i'm querying this data over time to be able to estimate RAM requirements when compared to the sizes of the lists it keeps inside.

    So... Which one should I use and why?