Hello World


Monday, December 10, 2007

Determistic Finalization with IDisposable

Finalization, how it works?
Heap exhaustion/shutting down an application triggers a Garbage Collection. Class that manage external resources like DB connection, file handler should implement Finalization to improve the system performance – proactively release the (external) resource once finished use.
However, objects that require finalization complicate the collection process. An object with a finalizer is not immediately released. How is works? GC checks metadata of every object type in the scan. If the object implements the Finalize() method, GC doesn't destroy it. Instead it is marked as reachable and it moved from it's orginal graph to another object graph- a special queue called finalized queue, which establishes a reference to the object, preventing its collection. GC proceeds. Meanwhile, a seperate background thread iterates all objects in the finalized queue, calling Finalize() on each and removes the finalized object from the finalization queue.
There is a fair standard pattern on implementing Finalize, such like define it as proteced+virtual; calling parent's Finalize at the end of your call... In fact c# comes with a code template destructor (~{MyClassName}), compiler expands it to full size Finalize() method at compiling.
Only after finalization can the object be removed from memory during the *next* GC pass. As a side effect of surviving one collection pass, the object is promoted into a higher generation, further delaying its eventual collection-
Non-Determistic Finalization meaning Garbage collection time is unpreditable. The application should not rely on GC to clean up expensive resources, which hurts scalability and performance.
Determistic Finalization
To free up used resources, client should proactively release used resource, such like DB connection when it is no longer used, instead of relies on GC.
-The Open()/Close() Pattern
Use object pool to manage objects without really destroy an object. Many .Net framwork classes use this pattern, E.g. file, stream (I/O, memory, network), DB connection, communication port etc.

-IDisposable Pattern
Classes that require finalization should implement the IDisposable interface in order to allow client to provide a determistic finalisatoin - short-circuit GC finalization and avoid the garbaged object (which uses external resource, say) promoted to G1.
There are two ways that classes that implement IDisposable have their objects being cleaned up.
1) Client code explicitly calls Dispose.
Your implementation in Dispose has the _chance_ to explicitly clean-up unmanaged resource as well as managed resource (by GC). By now your unmanaged resource is already freed up, there is no point to put the object in finalize queue to delays its release (G1), you should supress this by calling GC.SuppressFinalize(this);

2) Destructor Finalize method calls Dispose. This is a fallback plan if client fails to clean up.
In this case the Dispose method can only clean up unmanaged resource. Because during finalization, GC may have already removed the object for which Dispose is called (in following code example, the timer object). In this case, Dispose calls to clean this object, it will fail on null referencing.

No comments:

4GuysFromRolla.com Headlines