Tuesday, August 3, 2010

The .NET Garbage Collector

Exert from Pro C# by Andrew Troelsen
When you are building your C# applications you are correct to assume that the managed heap will take care of itself without your direct intervention. In fact, the golden rule of .NET memory management is very simple:

RULE: Allocate an object onto the managed heap using the new keyword and forget about it.

Once "new-ed", the garbage collector (GC) will destroy the object when it is no longer needed. The next obvious question is, of course, "How does the GC know when an object is no longer needed"? An excellent question.  The short answer is that the GC removes an object from the heap when it is unreachable by any part of your code.  

When an object goes out of scope it becomes a "candidate" for garbage collection. Understand however that you cannot guarantee that this object will be reclaimed from memory immediately after an object goes out of scope and is no longer unreachable. All you can assume at this point is that when the CLR performs the next garbage collection the object will then be safely destroyed.

As you will most certainly discover, programming in a garbage collected environment will greatly simplify your application development.  In stark contrast C++ programmers will be painfully aware that if they fail to manually delete heap-allocated objects, memory leaks are not far behind.  In fact, tracking down memory leaks is one of the most time consuming (and tedious) aspects aspects of programming with unmanaged languages.  By allowing the GC to be in charge of destroying objects, the burden of memory management has been taken from you shoulders and placed onto the CLR.  Effectively making us developers much more productive writing more business logic for less time.  In fact you may never need to use a memory profiler tool to track down memory leaks ever again!

NOTE: If you have any background in COM development, do know that .NET objects do not maintain an internal reference counter, and therefore managed objects do not expose methods such as AddRef() and Release().

If the managed heap does not contain sufficient space to host a requested new object, then a garbage collection run will occur immediately.

When garbage collection takes place the runtime will temporarily suspend all active threads within the current process.  The GC process has received considerable attention over the years and is highly optimised, and you will seldom (if ever) notice this brief interruption in your application.

The GC maintain two distinct heaps. One for very large objects and one for all others.  The heap for very large objects is less frequently consulted for collection, a good reason to follow good Object Oriented design principles and avoid very large objects.

So will objects that have unmanaged resources be GC'ed? Yes, but you need to be sure to release and clean up an unmanaged resources, because if you don't the objects will be destroyed by the GC, but your unmanaged resources may not be cleaned up leaving things in an inconsistent state.  To clean up unmanaged resources use a finalizer (destructor). 
RULE: The only reason to override Finalize() is if your C# class is making use of unmanaged resources via PInvoke or complex COM interoperability tasks (typically via the System.Runtime.InterOpServices.Marshal type).
Remember however, you cannot predict when an object is going to be destroyed by the GC and Finalize() called.  So if you have expensive resources that you want to free up sooner consider implementing IDisposable.

No comments:

Post a Comment