Difference Between Perf Data Reported by Different Tools – 2

Managed Heap Size

We have both .NET CLR Memory perf counters and SoS extensions that report manged heap size related data.

Difference 2

There are a few .NET CLR Memory counters that are related to the managed heap size:

# Total Committed Bytes

# Total Reserved Bytes

I explained what these counters mean here.

Now, how are they related to the values you see when you do a !SOS.eeheap –gc?

0:003> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x01245078
generation 1 starts at 0x0124100c
generation 2 starts at 0x01241000
ephemeral segment allocation context: (0x0125a900, 0x0125b39c)
 segment    begin allocated     size
001908c0 793fe120  7941d8a8 0x0001f788(128904)
01240000 01241000  0125b39c 0x0001a39c(107420)
Large object heap starts at 0x02241000
 segment    begin allocated     size
02240000 02241000  02243250 0x00002250(8784)
Total Size   0x3bd74(245108)
GC Heap Size   0x3bd74(245108)

The allocated column indicates the end of the last live object on the segment. So for gen0 and LOH it changes as the managed threads allocate, unlike the .NET CLR Memory counters which only reflect the end of the last live object on the segment when the last GC’s happened (at the end of last GC).

The # Bytes in All Heaps counter  under .NET CLR Memory counter is kind of misleading. The explanation says it’s the bytes in “all heaps” but really it’s gen1+gen2+LOH in CLR 2.0, so it doesn’t include gen0 ‘cause most of the time gen0 size is 0 right after a GC. So if you break into your process under the debugger and use the !sos.eeheap –gc command you will most likely get a value that’s the same as this counter. But if you break between 2 GCs the value you get from !eeheap –gc will always be larger than the value of this counter.

If you are concerned with the true amount of memory that the managed heap commits (which is usually what you need to worry about) you should use the # Total Committed Bytes counter.

Comments (7)

  1. Marteen Rojo says:

    Dear Maoni,

    its with great interest that I’ve been reading your blog posts.

    We are sizing/capacity planning my company’s application’s performance,

    So for each application-centric object we create, memory is measured (so as to figure out how many we can create etc.).

    Can you explain the difference between these 2 performance counters?

    ProcessPrivate Bytes and

    .NET CLR Memory # Total committed Bytes ?

    I thought that ProcessPrivate Bytes showed , basically, how much memory was actually in use, but now I think the "# Total committed Bytes" is what should be measured.



  2. Marteen, the .NET CLR Memory# Total Committed Bytes is only the private bytes used for *managed heap*. In your process you have other things that will contribute to the private bytes like if you make native allocations either yourself or in some modules that you use and ProcessPrivates Bytes shows all private bytes used in the process.

  3. leoleo says:

    This is really interesting, so it looks like the heap sizes from perf counters will always be smaller than !sos.eeheap -gc. For one it doesn’t include gen0 but that’s a small portion relatively speaking but also it is post GC data which means the heaps are all "cleaned up". Does that sound about right?

  4. Mak says:


          What does it mean if .NET CLR Memory # Total committed Bytes  is much greater than GC Heap Size. I have a case where Total Committed bytes is 150 MB and GC Heap size is 80 MB.



  5. Mak, we do leave some space at the end of the ephemeral segment committed ’cause we don’t want to decommit it and have to commit it again for allocations. This is what causes the descrepency.