- Always leave local variable.
- Set class variables, events etc to null.
These questions might come to any developer who has just came to .NET environment. As for me too, I was doing the application just blindly taking it account that this might be the basic usage of .NET applications, and there might be a hidden hand for me who works for me in background. Until after few days, I got an alternative to call the Garbage collection using
GC.Collect()
But according to the documentation, GC.Collect() is a request.It is not guaranteed that the Collection process will start after calling the method and the memory is reclaim So, there is still uncertainty whether actually the Garbage Collection will occur or not.
Why GC.Collect is discouraged ?
GC.Collect actually forces the Garbage collection to invoke its collection process out of its regular cycle. It potentially decreases the performance of the application which calls it. As GC.Collect runs in the thread on which it is called, it starts and quickly finishes the call. In such phase of GC collection, actually the memory is not been reclaimed, rather it just produces a thorough scan on objects that are out of scope. The memory ultimately freed whenever Full Garbage collection takes place.
For reference you can read Scotts blog entry.
Whats new in .NET 4.0 (or .NET 3.5 SP1)
Well, GC is changed a bit with the introduction of .NET 4.0, so that the programmer have better flexibility on how to use GC. One of such changes is the signature of GC.Collect()
Initially, GC.Collect only allows you to use Optimization call. Now it has 3 overloads :
- GC.Collect () : Forces an immediate garbage collection for all generations
- GC.Collect(int) : You pass the Generation 0 to specified generation to collect all generation starting from 0.
- GC.Collect(int, GCCollectionMode) : You can also specify the CollectionMode in addition to it. The CollectionMode can be CollectionMode.Force, CollectionMode.Optimized, and Default which is Forced.
So its a great relief to all of you right?
GC Notifications
Another feature that is introduced with GC in .NET 3.5 SP 1 is to produce notifications whenever GC collection is about to begin and GC collection is completed successfully. Say you are between a very resource consuming phase of your application, GC notification will allow you to get notified that GC is approaching, so that you could stop the current process and wait for GC to complete. This makes your application to run smoothly. So how can you do this ? Lets look at the steps :
- Call GC.RegisterForFullGCNotification to allow for notifications when GC is approaching.
- Create a new thread from the application and start poll continuously in an infinite loop to methods GC.WaitForFullGCApproach and/or GC.WaitForFullGCComplete methods.
- Both the method returns GCNotificationStatus.Succeeded when the notification has to be raised.
- In Calling thread use GC.CancelFullGCNorification to unregister the notification process.
public class MainProgram { public static List<char[]> lst = new List<char[]>(); public static void Main(string[] args) { try { // Register for a notification. GC.RegisterForFullGCNotification(10, 10); // Start a thread using WaitForFullGCProc. Thread startpolling = new Thread(() => { while (true) { // Check for a notification of an approaching collection. GCNotificationStatus s = GC.WaitForFullGCApproach(1000); if (s == GCNotificationStatus.Succeeded) { //Call event Console.WriteLine("GC is about to begin"); GC.Collect(); } else if (s == GCNotificationStatus.Canceled) { // Cancelled the Registration } else if (s == GCNotificationStatus.Timeout) { // Timeout occurred. } // Check for a notification of a completed collection. s = GC.WaitForFullGCComplete(1000); if (s == GCNotificationStatus.Succeeded) { //Call event Console.WriteLine("GC has ended"); } else if (s == GCNotificationStatus.Canceled) { //Cancelled the registration } else if (s == GCNotificationStatus.Timeout) { // Timeout occurred } Thread.Sleep(500); } }); startpolling.Start(); //Allocate huge memory to apply pressure on GC AllocateMemory(); // Unregister the process GC.CancelFullGCNotification(); } catch { } } private static void AllocateMemory() { while (true) { char[] bbb = new char[1000]; // creates a block of 1000 characters lst.Add(bbb); // Adding to list ensures that the object doesnt gets out of scope int counter = GC.CollectionCount(2); Console.WriteLine("GC Collected {0} objects", counter); } } }
Here when the program starts I have called RegisterForFullGCNotification. This call makes registers the GC to start notifying using the notifiers. Please note that the call to RegisterForFullGCNotification will fail if a concurrent GC is enabled. You will see "This API is not available when the concurrent GC is enabled.". Concurrent GC means the garbage collection will run in separate threads concurrently. If your application has to do some heavy task, leave concurrent GC enabled. This makes the GC run collection without interrupting the applicaition thread. For Asp.net application, you should disable concurrentGC.
To Disable Concurrent GC, add App.config and put
<configuration> <runtime> <gcConcurrent enabled="false" /> </runtime> </configuration>
After concurrent GC is disabled you can run the application. After calling RegisterForFullGCNotification, we start a new thread. In the thread we continuously polling WaitForFullGCApproach which returns GCNotificationStatus.Succeeded whenever the GC is approaching. It is better to call GC.Collect in this situation to ensure that collection starts immediately.
We also poll WaitForFullGCComplete which returns GCNotificationStatus.Succeeded whenever the GC collection is complete.
We use GC.CancelFullGCNotification() to stop using Notiification.
From the main thread, we continuously allocating memory to check when GC collection occurs. The GC.CollectionCount to determine how many GC collection took place at a given instant of time. Use 0 - 2 to check each generation individually.
Download Sample application - 30KB
Please feel free to leave your comment on this new feature.
No comments:
Post a Comment
Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.