The GC does an amazing job of managing managed memory… We really work hard to make sure pages stay hot, and the memory is cached where you need it…. But the reality of the world is that for many folks it is not just managed memory they have to deal with.  Often you have to deal with memory allocated by legacy APIs in an unmanaged heap which the GC does not directly manage or external non-memory resources.  We added a couple of neat features to the CLR in Whidbey to help address these issues.  I was just in the middle of adding slides about these to my Design .NET Class Libraries class that I teach to WinFX (and other) developers here at Microsoft and I thought I’d share about these cool features…

 

  1. Cheap managed object holding an expensive unmanaged object.

Consider a class that has a very small managed instance size but holds a pointer to a very large chunk of unmanaged memory.  Even after no one is referencing the managed instance it could stay alive for a while because the GC sees only the managed instance size it does not think it is “worth it” to free the instance.  So we need to “teach” the GC about the true cost of this instance so that it will accurately know when to kick of a collection to free up more memory in the process.  

 

         Useful when you have a disproportionate ratio of managed, to unmanaged resources

         GC alters it’s strategy, to increase the number of collections performed

         GC.RemoveMemoryPressure when your object is freed, to allow the GC to return to its standard strategy

 

class Bitmap {

   private long _size;

   Bitmap (string path ) {

      _size = new FileInfo(path).Length;

      GC.AddMemoryPressure(_size);

      // other work

   }

   ~Bitmap() {

      GC.RemoveMemoryPressure(_size);
         // other work

   }

}

 

In the constructor we “add pressure” to the GC in the form of the number of bytes the bitmap will store in unmanaged memory and in the finalizer we remove that pressure.

 

  1. Handling a limited number of resources.

In some cases there exists only a limited number of a resource (a HDC, Hwnd, database connection, etc) and you want to manage your usage of those resources carefully, but you’d like to hide that management from your users.  The HandleCollector is here to help! It essentially does the bean counting for you and kicks the GC when you start to run out of resources to perform a collection to try to free some of the resource.  Notice this basic strategy was used privately by WinForms in V1 and is now made public in Whidbey.

 

         HandleCollector keeps track of a limited number of handles

         typically, unmanaged resource handles: HDCs, HWnds, etc

         When you allocate a new handle, call Add.

         When you freeing, call Remove

         As you add to the collector, it may perform a GC.Collect, to free existing handles, based on the current count, and the number of resources available

HandleCollector(string name, int initialThreshold,  int maximumThreshold);

name: allows you to track each handle type separately, if needed

initialThreshold: the point at which collections should begin being performed

maximumThreshold: the point at which collections MUST be performed. This should be set to the maximum number of available handles

 

static readonly HandleCollector GdiHandleType =
   new HandleCollector( “GdiHandles”, 10, 50);

 

static IntPtr CreateSolidBrush() {

   IntPtr temp = CreateSolidBrushImpl(…);

   GdiHandleType.Add();

   return temp;

}

 

internal static void DeleteObject(IntPtr handle) {

   DeleteObjectImpl(handle);

   GdiHandleType.Remove();

}