How to receive a full GC notification with .NET 4.0

While scanning GC class members in IntelliSense with VS 2010 I noticed a few that looked unfamiliar. Turns out new feature allows receiving full GC notifications using the following methods:

  • GC.RegisterForFullGCNotification(..)
  • GC.CancelFullGCNotification(..)
  • GC.WaitForFullGCApproach(..)
  • GC.WaitForFullGCComplete(..)

This is how MSDN explains the main user scenario for these notifications:

There are situations in which a full garbage collection by the common language runtime may adversely affect performance. This can be an issue particularly with servers that process large volumes of requests; in this case, a long garbage collection can cause a request time-out. To prevent a full collection from occurring during a critical period, you can be notified that a full garbage collection is approaching and then take action to redirect the workload to another server instance. You can also induce a collection yourself, provided that the current server instance does not need to process requests.

I decided to try them out and wrote a test WPF app that displays a message when full GC is about to start and then another message when full GC is complete. MSDN provides a decent sample that explains the usage pattern, but in a nutshell it is:

  1. On the main thread call GC.RegisterForFullGCNotification(..)

  2. Spawn a separate thread  that will call WaitForFullGCApproach and then WaitForFullGCComplete. In my case I was calling these methods with infinite timeout to keep it simple, so it would either return Succeeded or Canceled. Then I would send notification to the main thread that GC is either approaching or completed. Here's how 'GC notification procedure' looked.

    private void GCNotifyProc()
    {
    while (true)
    {
    var gcApproachStatus = GC.WaitForFullGCApproach(-1); //wait indefinitely
    if (gcApproachStatus == GCNotificationStatus.Succeeded)
    //notify the main thread that full GC is imminent
    Dispatcher.Invoke(new Action(() => NotifyGCStart()));
    else
    // Main thread must have called GC.CancelFullGCNotification(..),
    // or notification failed, exit the procedure

    return;

    var gcCompleteStatus = GC.WaitForFullGCComplete(-1); //wait indefinitely
    if (gcCompleteStatus == GCNotificationStatus.Succeeded)
    //notify the main thread that full GC has completed
    Dispatcher.Invoke(new Action(() => NotifyGCComplete()));
    else
    // Main thread must have called GC.CancelFullGCNotification(..),
    // or notification failed, exit the procedure

    return;
    }
    }

  3. To stop listening for GC notifications, call GC.CancelFullGCNotification(..) from the main thread. At this point my background thread that was waiting inside WaitForFullGCApproach or WaitForFullGCComplete would return with GCNotificationStatus.Canceled and exit the procedure.

 

While this seems quite straightforward, I'd like to point out a few details that I learnt or realized while playing with GC notifications.

  1. Concurrent GC needs to be disabled to use GC notifications. To disable add the following to your config file: <configuration>
       <runtime>
           <gcConcurrent enabled="false"/>
       </runtime>
    </configuration>
  2. Full GC Notifications... are full GC notifications. Well, this is sure obvious, unless you, like me, forgot or wasn't sure what 'full' really means. Full GC means GC on Generation 2, while ephemeral GC means GC  on Generation 0 and 1. To recall, object is promoted to Gen2 after it has survided Gen1 GC with the exception of Large Object Heap objects that are bigger than 85K bytes and become part of Gen2 right from the start. So, this notification mechanism are for Gen2 collections only.
  3. And finally, when WaitForFullGCApproach(..) returns Succeeded, all it means is that conditions for full GC are favourable and full GC is imminent. No guarantees are made about when exactly it will run. The name of the method reflects it clear enough, although I would probably make it sound even less deterministic.

My post was just scratching the surface, but if you're looking for more in-depth info on GC notifications, I'd recommend the following blog:  https://blogs.msdn.com/maoni/archive/2008/11/19/so-what-s-new-in-the-clr-4-0-gc.aspx