Friday, April 3, 2009

ASP.NET Garbage Collection

1 What is garbage collection?

Ans. Garbage collection is a system whereby a run-time component takes responsibility for managing the lifetime of objects and the heap memory that they occupy. This concept is not new to .NET - Java and many other languages/runtimes have used garbage collection for some time.

2. Is it true that objects don't always get destroyed immediately when the last reference goes away?

Ans. Yes. The garbage collector offers no guarantees about the time when an object will be destroyed and its memory reclaimed.
There is an interesting thread in the archives, started by Chris Sells, about the implications of non-deterministic destruction of objects in C#: http://discuss.develop.com/archives/wa.exe?A2=ind0007&L=DOTNET&P=R24819
In October 2000, Microsoft's Brian Harry posted a lengthy analysis of the problem: http://discuss.develop.com/archives/wa.exe?A2=ind0010A&L=DOTNET&P=R28572
Chris Sells' response to Brian's posting is here: http://discuss.develop.com/archives/wa.exe?A2=ind0010C&L=DOTNET&P=R983

3. Why doesn't the .NET runtime offer deterministic destruction?

Ans. Because of the garbage collection algorithm. The .NET garbage collector works by periodically running through a list of all the objects that are currently being referenced by an application. All the objects that it doesn't find during this search are ready to be destroyed and the memory reclaimed. The implication of this algorithm is that the runtime doesn't get notified immediately when the final reference on an object goes away - it only finds out during the next sweep of the heap.
Futhermore, this type of algorithm works best by performing the garbage collection sweep as rarely as possible. Normally heap exhaustion is the trigger for a collection sweep.

4. Is the lack of deterministic destruction in .NET a problem?

Ans. It's certainly an issue that affects component design. If you have objects that maintain expensive or scarce resources (e.g. database locks), you need to provide some way for the client to tell the object to release the resource when it is done. Microsoft recommend that you provide a method called Dispose() for this purpose. However, this causes problems for distributed objects - in a distributed system who calls the Dispose() method? Some form of reference-counting or ownership-management mechanism is needed to handle distributed objects - unfortunately the runtime offers no help with this.

5. Does non-deterministic destruction affect the usage of COM objects from managed code?

Ans. Yes. When using a COM object from managed code, you are effectively relying on the garbage collector to call the final release on your object. If your COM object holds onto an expensive resource which is only cleaned-up after the final release, you may need to provide a new interface on your object which supports an explicit Dispose() method.

6. I've heard that Finalize methods should be avoided. Should I implement Finalize on my class?

Ans. An object with a Finalize method is more work for the garbage collector than an object without one. Also there are no guarantees about the order in which objects are Finalized, so there are issues surrounding access to other objects from the Finalize method. Finally, there is no guarantee that a Finalize method will get called on an object, so it should never be relied upon to do clean-up of an object's resources.
Microsoft recommend the following pattern:
public class CTest : IDisposable
{
public void Dispose()
{
... // Cleanup activities
GC.SuppressFinalize(this);
}

~CTest() // C# syntax hiding the Finalize() method
{
Dispose();
}
}
In the normal case the client calls Dispose(), the object's resources are freed, and the garbage collector is relieved of its Finalizing duties by the call to SuppressFinalize(). In the worst case, i.e. the client forgets to call Dispose(), there is a reasonable chance that the object's resources will eventually get freed by the garbage collector calling Finalize(). Given the limitations of the garbage collection algorithm this seems like a pretty reasonable approach.

7. Do I have any control over the garbage collection algorithm?

Ans. A little. For example, the System.GC class exposes a Collect method - this forces the garbage collector to collect all unreferenced objects immediately.
5.8 How can I find out what the garbage collector is doing?
Lots of interesting statistics are exported from the .NET runtime via the '.NET CLR xxx' performance counters. Use Performance Monitor to view them.

No comments: