Search This Blog

Thursday, August 26, 2010

Garbage Collection in .Net

This is my first post and thought of b-logging in some stuff for the technical guys. This post will be useful only to those who are little bit aware of what .Net is and what can it do. I am going to put some information on the Garbage collection concept in .Net. Hopefully that will help in understanding the basic of GC!

Garbage Collector - .Net

Memory management is one of those housekeeping duties that takes a lot of programming time away from developing new code while you track down memory leaks. A day spent hunting for an elusive memory problem usually isn’t a productive day. .NET hopes to do away with all of that within the managed environment with the garbage collection system. Garbage collection runs when your application is apparently out of free memory, or when it is implicitly called but its exact time of execution cannot be determined. Let’s examine how the system works.


When your application requests more memory, and the memory allocator reports that there is no more memory on the managed heap, garbage collection is called.The garbage collector starts by assuming everything in memory is trash that can be freed. It then walks though your application’s memory, building a graph of all memory that is currently referenced by the application. Once it has a complete graph, it compacts the heap by moving all the memory that is genuinely in use together at the start of the free memory heap. After this is complete, it moves the pointer that the memory allocator uses to determine where to start allocating memory from the top of this new heap. It also updates all of your application’s references to point to their new locations in memory.This approach is commonly called a mark and sweep implementation.

Normally you will just let the CLR take care of running garbage collection when it is required. However, at times you may want to force the garbage collector to run, perhaps before starting an operation that is going to require a large amount of memory.To do this, just call GC.Collect(). And if you want to report on your memory use at various points during your application’s execution to help you determine when might be a good time to force collection, you can use

GC.GetTotalMemory(bool forceFullCollection).

The methods in this class influence when garbage collection is performed on an object, and when resources allocated by an object are released. Properties in this class provide information about the total amount of memory available in the system and the age category, or generation, of memory allocated to an object.

The garbage collector tracks and reclaims objects allocated in managed memory. Periodically, the garbage collector performs garbage collection to reclaim memory allocated to objects for which there are no valid references. Garbage collection happens automatically when a request for memory cannot be satisfied using available free memory. Alternatively, an application can force garbage collection using the Collect method.

Garbage collection consists of the following steps:

1. The garbage collector searches for managed objects that are referenced in managed code.

2. The garbage collector attempts to finalize objects that are not referenced.

3. The garbage collector frees objects that are not referenced and reclaims their memory.

During a collection, the garbage collector will not free an object if it finds one or more references to the object in managed code. However, the garbage collector does not recognize references to an object from unmanaged code, and might free objects that are being used exclusively in unmanaged code unless explicitly prevented from doing so. The KeepAlive method provides a mechanism that prevents the garbage collector from collecting objects that are still in use in unmanaged code.

Aside from managed memory allocations, implementations of the garbage collector do not maintain information about resources held by an object, such as file handles or database connections. When a type uses unmanaged resources that must be released before instances of the type are reclaimed, the type can implement a finalizer.

In most cases, finalizers are implemented by overriding the Object.Finalize method; however, types written in C# or C++ implement destructors, which compilers turn into an override of Object.Finalize. In most cases, if an object has a finalizer, the garbage collector calls it prior to freeing the object. However, the garbage collector is not required to call finalizers in all situations; for example, the SuppressFinalize method explicitly prevents a finalizer from being called. Also, the garbage collector is not required to use a specific thread to finalize objects, or guarantee the order in which finalizers are called for objects that reference each other but are otherwise available for garbage collection.

In scenarios where resources must be released at a specific time, classes can implement the IDisposable interface, which contains the IDisposable.Dispose method that performs resource management and cleanup tasks. Classes that implement Dispose must specify, as part of their class contract, if and when class consumers call the method to clean up the object. The garbage collector does not, by default, call the Dispose method; however, implementations of the Dispose method can call methods in the GC class to customize the finalization behavior of the garbage collector.

It is recommended, but not required, that garbage collectors support object aging using generations. A generation is a unit of measure of the relative age of objects in memory. The generation number, or age, of an object indicates the generation to which an object belongs. Objects created more recently are part of newer generations, and have lower generation numbers than objects created earlier in the application life cycle. Objects in the most recent generation are in generation zero.

Notes to Implementers This implementation of the garbage collector supports three generations of objects. MaxGeneration is used to determine the maximum generation number supported by the system. Object aging allows applications to target garbage collection at a specific set of generations rather than requiring the garbage collector to evaluate all generations.

Allows an Object to attempt to free resources and perform other cleanup operations before the Object is reclaimed by garbage collection. Finalize is protected and, therefore, is accessible only through this class or a derived class.

This method is automatically called after an object becomes inaccessible, unless the object has been exempted from finalization by a call to SuppressFinalize. During shutdown of an application domain, Finalize is automatically called on objects that are not exempt from finalization, even those that are still accessible. Finalize is automatically called only once on a given instance, unless the object is re-registered using a mechanism such as ReRegisterForFinalize and GC.SuppressFinalize has not been subsequently called.

GC Methods

GC.AddMemoryPressure(); - Informs runtime about large amount of memory allocation that should be taken into consideration when GC is scheduled to run.

GC.Collect(); - Forces garbage collection of all generations.

GC.CollectionCount(int generation); - Returns the number of times garbage collection has occurred for the specified generation.

GC.GetGeneration(); - Returns the current generation number.

GC.GetTotalMemory(true); - Returns the number of bytes thought to be allocated. True indicates if this method can wait for short interval of time before returing, to allow the garbage collector to collect and finalize.

GC.KeepAlive(); - GC does not recognize the referenced objects in unmanaged code and clears up by default. This method prevents an object being cleared from unmanaged code.

GC.MaxGeneration(); - Gets the maximum number generations supported by system.

GC.RemoveMemoryPressure() – Informs runtime that the large amount of memory allocation has been released and need not be considered for GC.

GC.ReRegisterForFinalize(); - Finalize is ran only once for an object. If we want to to run the finalize again for an object then this method could be used unless we have not called the suppressFinalize subsequently for that object.

GC.SuppressFinalize(); - Finalize is by default called for all the object that come under GC, untill this method is explicitly called to prevent the finalize method being called for that object.

GC.WaitForPendingFinalizers(); - Current thread is suspended to wait for another thread that is processing the queue of finalizers finishes up.

1 comment: