Friday, June 13, 2008
Times when one should call GC.Collect – See Post
GC.Collect an Overhead -
A lot of people have the belief that calling GC.Collect manually will reduce the memory usage of your application and, thereby, increase performance. Yes it is true that Calling GC.Collect will potentially decrease the memory usage, but but …. it does so by forcing an "out of cycle" collection to occur.
The reason I say "potentially" is that in this out of cycle collection there may not be any objects that are able to be reclaimed. You also suffer a performance hit during the collection cycle.
The default GC.Collect method causes a full collection of all generations. Full collections are expensive because literally every live object in the system must be visited to ensure complete collection. Needless to say, exhaustively visiting all live objects could, and usually does, take a significant amount of time.
Even though garbage collection cycles run very quickly, in order for the GC to do it's job properly it Freezes your applications main thread before starting the collection cycle. When the collection is finished, the thread is Unfrozen. The end result of this is that you are context switching between threads and freezing your application.
There are times when you should call GC.Collect(), but generally it is discouraged except for debugging purposes. The time when avoidng GC.Collect is not possible, you end up with using and eventually face performance hit.
To avoid this performance hot in unavoidable situations – Changes have been made in the GC in the .NET Framework 3.5 release. The change adds an overload to the GC.Collect() method.
void System.GC.Collect(int generation, System.GCCollectionMode mode)
This overload - Forces a garbage collection from generation zero through a specified generation, at a time specified by a GCCollectionMode value.
What this really means is that you can use the mode parameter to specify when the collection should occur. The valid values for mode are:
This is currently equivalent to Forced.
Forces the garbage collection to occur immediately. This is the same behavior as if you called GC.Collect without specifying the mode.
Allows the garbage collector to determine the optimal time to reclaim objects.
Using the Default or Forced modes is really the same as calling GC.Collect(), so you shouldn't use them except in specific cases (as shown in Rico's blog post).
However, the Optimized mode tells the GC "I want to do an out of cycle collection, but only if it's needed." Ultimately, the GC considers a lot of different factors in deciding this, including Amount Of Memory considered garbage and the Amount Of Heap fragmentation. If the GC decides a collection isn't needed, it won't run one and the call will have no effect.
Even with this new overload, I still recommend against using GC.Collect (or this overload with the Forced or Default modes) except under very specific circumstances. If you feel you absolutely must add your own calls to GC.Collect, make sure to use the overload and a mode of Optimized. Also, if you have existing code that makes use of calls to GC.Collect, you should take the time to review each of those calls to see if they are still necessary and consider changing them to call the overload with a mode of Optimized.
Thanks & Regards,
Arun Manglick || Senior Tech Lead