During my talk on Garbage Collection in .NET at the
Jacksonville Code Camp 2007, Joe Healy mentioned that I should take a look at
the changes made to the GC in the .NET Framework 3.5 release. (This is based on
the Beta 2 release, but it should be pretty stable at this point.)
After doing some research using the SSCLI 2.0 code
base to look at the GC class as it exists in .NET 2.0 and Reflector to look at
it in .NET 3.5, I found the single change that was made. (For those of you
wondering why I used SSCLI, when you install the .NET Framework 3.5 it also
installs Service Pack 1 for .NET 2.0).
In my talk, and in most of the forum discussions I
have about GC, I mention that you really shouldn't "help" the GC by
calling GC.Collect. A lot of people have the belief that calling GC.Collect
manually will reduce the memory usage of your application and, thereby,
increase performance. Calling GC.Collect will potentially decrease
the memory usage, 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.
Even though garbage collection cycles run very quickly, in order for the GC to
do it's job properly it must freeze 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 a lot more often than you would be
without the calls to GC.Collect, which ultimately will start to hurt your
performance. There are times when
you should call GC.Collect(), but generally it is discouraged except for
debugging purposes.
So, what is the change to the GC? The change adds
an overload to the GC.Collect() method:
1: void System.GC.Collect(int generation,
System.GCCollectionMode mode)
According to the MSDN documentation for
this overload, this "forces a garbage collection from generation zero
through a specified generation, at a time specified by aGCCollectionMode 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:
- Default: This is
currently equivalent to Forced.
- Forced: Forces the
garbage collection to occur immediately. This is the same behavior as if
you called GC.Collect without specifying the mode.
- Optimized: 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.
One other thing to keep in mind if you use this new
overload is that it doesn't guarantee that all inaccessible objects in the
specified generation will be reclaimed.
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.
No comments:
Post a Comment