18

I'm trying to measure, in a C# programm, the memory usage.

I'd like to know the C# equivalent of this Java function :

ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getCommitted()

that represent the total memory allocated for the heap. I need this to know the total size of memory allocated for my C# programm.

Then in Java I can get the used memory with :

ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()

Currently I use this in C# to get used memory :

Process_Memory = MyProcess.PrivateMemorySize64;

But I'm not totally sure that it's the equivalent.

So in resume how can I get the total allocated space for my C# application and the current use at a time t?

EDIT :

From the answers and further research I've determine this :

Current memory in use

System.GC.GetTotalMemory(false);

Give the number of bytes currently allocated in managed memory. (http://msdn.microsoft.com/fr-fr/library/system.gc.gettotalmemory.aspx)

This method return a low value and I'm pretty sure it's not really a representation of all memory in use as I can get with getUsed() in Java. In java for the same application used memory start at 5MB and go to 125MB max. With C# I get from 1 to 5 MB with above method.

It seems that :

MyProcess.PrivateMemorySize64; // return ~=25MB

or

MyProcess.WorkingSet64;  //return ~=20MB

Give a more accurate value of all the memory in use. But I don't know wich one I should use...

For the global allocated memory this article suggests to use :

Process_MemoryEnd1 = MyProcess.VirtualMemorySize64;

It return always the same value along the programm, about 169MB that seems fair compared to Java : from 64MB to 170MB max

I'm still looking for an accurate answer all I found is very vague and I'm not very familiar with Windows memory management, I'm not really sure to undertand the docs I found :/

alain.janinm
  • 19,951
  • 10
  • 65
  • 112

2 Answers2

18

Heres one way, using the GC:

    public void Test()
    {
        long kbAtExecution = GC.GetTotalMemory(false) / 1024;

        // do stuff that uses memory here 

        long kbAfter1 = GC.GetTotalMemory(false) / 1024;
        long kbAfter2 = GC.GetTotalMemory(true) / 1024;

        Console.WriteLine(kbAtExecution + " Started with this kb.");
        Console.WriteLine(kbAfter1 + " After the test.");
        Console.WriteLine(kbAfter1 - kbAtExecution + " Amt. Added.");
        Console.WriteLine(kbAfter2 + " Amt. After Collection");
        Console.WriteLine(kbAfter2 - kbAfter1 + " Amt. Collected by GC.");         
    }

Or alternatively using System.Diagnostics.PerformanceCounter to get working set info:

PerformanceCounter performanceCounter = new PerformanceCounter();

performanceCounter.CategoryName = "Process";

performanceCounter.CounterName = "Working Set";

performanceCounter.InstanceName = Process.GetCurrentProcess().ProcessName;

Console.WriteLine(((uint)performanceCounter.NextValue()/1024).ToString("N0"));
Sean Thoman
  • 7,429
  • 6
  • 56
  • 103
  • Thanks for the answer. So, as the doc says, `GC.GetTotalMemory(false)` return the number of bytes currently allocated in managed memory. I think it may be the equivalent of getUse() in java. But how I get the entire space allocated? Does ` System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64` represent that value? – alain.janinm Feb 22 '12 at 23:46
  • For the second solution it raised a `System.InvalidOperationException` – alain.janinm Feb 22 '12 at 23:53
  • @alain.janinm, Not sure why. Works on my system. Whats the error or inner exception say? – Sean Thoman Feb 22 '12 at 23:57
  • Heu the problem is that VS give error in French so I will try to translate : Impossible to load the data of counter name, because an index is not valid '' as been read from register. – alain.janinm Feb 23 '12 at 00:09
  • Using your GC-based approach I was getting very inconsistent numbers (variations on the order of 16x) for the same block of code. By adding `GC.Collect();` and `GC.WaitForPendingFinalizers();` before it I was able to get *much* more consistent measurements. – DaveD Jun 05 '15 at 15:07
10

The GC static class provides all this type of information.

Your probably after GC.GetTotalMemory().

EDIT:

I beleive that attempts to workout your memory footprint based on currently rooted objects. IF you want the total size allocated for the process (i.e. including the free buffer) use the Process class. e.g.:

Process.GetCurrentProcess().WorkingSet64;
Tyson
  • 14,726
  • 6
  • 31
  • 43
  • Yes I know this but it give the actual size of objects in the managed heap, it's a low value. I don't think this is representative of all the allocated memory. – alain.janinm Feb 22 '12 at 23:39
  • Then I believe you just need to use all those properties of the `Process` class if you want raw allocated memory (i.e. not taking into account any of the managed GC functionality). `PagedMemorySize64`, `PrivateMemorySize64`, etc. – Tyson Feb 22 '12 at 23:45
  • Thanks, so I think if I want just the processus total allocated memory `PrivateMemorySize64` can be enough. I don't get what is paged memory... – alain.janinm Feb 22 '12 at 23:48
  • Well it's an edge case. If the physical RAM is full, the OS will use a chunk of your HDD as 'memory', called 'virtual memory'. So if your being really pedantic and want the total, you really should add them all up, just in case. I am not sure if `WorkingSet64` takes virtual memory into account. MSDN says "WorkingSet64: Gets the amount of physical memory allocated for the associated process." – Tyson Feb 22 '12 at 23:53
  • Ok so I want the total allocated memory I add `NonpagedSystemMemorySize64` + `PagedMemorySize64` + `PagedSystemMemorySize64` + `PrivateMemorySize64` + `WorkingSet64` ? – alain.janinm Feb 23 '12 at 00:04
  • Nope. `WorkingSet` is definetly the sum of atleast some of those. And it sounds like `PagedMemorySize == VirtualMemorySize`. I normally just use `WorkingSet` by itself. These are good questions though, perhaps the topic for a new question? – Tyson Feb 23 '12 at 00:54
  • I've edit the question rather than an other question, take a look ;) it's still quite unclear for me. – alain.janinm Feb 23 '12 at 13:27