Raymond Lewallen

Sponsors

The Lounge

Wicked Cool Jobs

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Performance Monitoring - Garbage Collection
I see this topic quite a bit on newsgroups and in microsoft chats. People ask how and what to monitor to check out the performance of their application. First and foremost, I tell people to get CLRProfiler.
The CLR Profiler includes a number of very useful views of the allocation profile, including a histogram of allocated types, allocation and call graphs, a time line showing GCs of various generations and the resulting state of the managed heap after those collections, and a call tree showing per-method allocations and assembly loads.
This is an invaluable tool.

This blog post topic isn't about the CLRProfiler though. This is about using PerfMon. When installing .Net, many, many new counters are added that allow you to get detailed and real-time information about the performance of your applications.  We are only going to talk about one set of those for monitoring garbage collections.  Launch PerfMon, and click the + to add new counters. In the Performance Object, select ".Net CLR Memory". It should look something similar to below:

Select a specific application to monitor from the right. You see on my machine the managed applications that are running. I can select OMEA Reader and profile its memory and GC usage.

I always use the following when doing checking the performance of the GC, along with their explanations:

# Gen 0 Collections - This counter displays the number of times the generation 0 objects (youngest; most recently allocated) are garbage collected (Gen 0 GC) since the start of the application. Gen 0 GC occurs when the available memory in generation 0 is not sufficient to satisfy an allocation request. This counter is incremented at the end of a Gen 0 GC. Higher generation GCs include all lower generation GCs. This counter is explicitly incremented when a higher generation (Gen 1 or Gen 2) GC occurs. _Global_ counter value is not accurate and should be ignored. This counter displays the last observed value.

Gen 0 Heap Size - This counter displays the maximum bytes that can be allocated in generation 0 (Gen 0); its does not indicate the current number of bytes allocated in Gen 0. A Gen 0 GC is triggered when the allocations since the last GC exceed this size. The Gen 0 size is tuned by the Garbage Collector and can change during the execution of the application. At the end of a Gen 0 collection the size of the Gen 0 heap is infact 0 bytes; this counter displays the size (in bytes) of allocations that would trigger the next Gen 0 GC. This counter is updated at the end of a GC; its not updated on every allocation.

# Gen 1 Collections - This counter displays the number of times the generation 1 objects are garbage collected since the start of the application. The counter is incremented at the end of a Gen 1 GC. Higher generation GCs include all lower generation GCs. This counter is explicitly incremented when a higher generation (Gen 2) GC occurs. _Global_ counter value is not accurate and should be ignored. This counter displays the last observed value.

Gen 1 heap size - This counter displays the current number of bytes in generation 1 (Gen 1); this counter does not display the maximum size of Gen 1. Objects are not directly allocated in this generation; they are promoted from previous Gen 0 GCs. This counter is updated at the end of a GC; its not updated on every allocation.

# Gen 2 Collections - This counter displays the number of times the generation 2 objects (older) are garbage collected since the start of the application. The counter is incremented at the end of a Gen 2 GC (also called full GC). _Global_ counter value is not accurate and should be ignored. This counter displays the last observed value.

Gen 2 heap size - This counter displays the current number of bytes in generation 2 (Gen 2). Objects are not directly allocated in this generation; they are promoted from Gen 1 during previous Gen 1 GCs. This counter is updated at the end of a GC; its not updated on every allocation.

Large Object Heap Size - This counter displays the current size of the Large Object Heap in bytes. Objects greater than 20 KBytes are treated as large objects by the Garbage Collector and are directly allocated in a special heap; they are not promoted through the generations. This counter is updated at the end of a GC; its not updated on every allocation.

# Bytes in all Heaps - This counter is the sum of four other counters; Gen 0 Heap Size; Gen 1 Heap Size; Gen 2 Heap Size and the Large Object Heap Size. This counter indicates the current memory allocated in bytes on the GC Heaps.

Promoted memory from Gen 0 - This counter displays the bytes of memory that survive garbage collection (GC) and are promoted from generation 0 to generation 1; objects that are promoted just because they are waiting to be finalized are not included in this counter. This counter displays the value observed at the end of the last GC; its not a cumulative counter.

Promoted memorty from Gen 1 - This counter displays the bytes of memory that survive garbage collection (GC) and are promoted from generation 1 to generation 2; objects that are promoted just because they are waiting to be finalized are not included in this counter. This counter displays the value observed at the end of the last GC; its not a cumulative counter. This counter is reset to 0 if the last GC was a Gen 0 GC only.

So I added all of these counters, and opened up OMEA Reader. I started up the PerfMon to start tracking and then did an update for all my webfeeds in OMEA Reader. As soon as that completed, I waited about 5 seconds and then took this snapshot of the report view of my performance monitor:

About a year ago, I spoke with a GC architect and he informed me that a very optimal ratio for generational GC's is 100-10-1 (gen 0-1-2). The app I'm profiling, under the circumstances and with resources available, doesn't reach that optimal level, but I've never profiled anything that does. This GC collection ratio is what you are primarily looking for from these counters. GC's are expensive and you'd like to see them kept at a minimum. You won't see a counter for LOH (large object heap) collections. They happen every time a Gen 2 collection occurs, so the collection counts are the same for both.


Posted Thu, Mar 31 2005 1:24 PM by Raymond Lewallen

[Advertisement]

Comments

Patrick Steele's .NET Blog wrote Most recently subscribed to.
on Wed, Apr 6 2005 8:00 PM
rolo wrote re: Performance Monitoring - Garbage Collection
on Thu, Jan 25 2007 4:53 PM

how change garbage collection levels?

where?

Raymond Lewallen wrote re: Performance Monitoring - Garbage Collection
on Thu, Jan 25 2007 5:03 PM

Rolo, the garbage collector promotes objects to other generations automatically.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us