GC prior to .NET 4.0
Most of us know how the GC generations work, but I’ll give a very brief rundown for those that haven’t looked at them yet, or may need a refresher.
There are 3 of them. 0, 1, 2.
When an item is first created, it’s considered a gen 0 item.
If it survives subsequent collections (because it’s still in use), it becomes a gen 1 item and so on.
gen 0 items mainly consist of instance variables, where as the later generation items are generally of a more global scope.
gen 2 items often stick around for the duration of the application.
The GC operates in the following modes
server or workstation.
You can change the modes in either your app.config (that’s per app) or in the machine.config (that’s machine wide)
<Configuration> <runtime> <gcServer enabled="false" /> <gcConcurrent enabled="true" /> </runtime> </Configuration>
As discussed by Tess Ferrandez (champion ASP.NET debugger)
The restrictions here are
- you can not run the server version on a single proc box, it will default to workstation
- you can not run concurrent while also running server
- if the runtime is hosted, the hosts GC mode will override the configuration
workstation (the default mode), concurrent workstation (the default if >0 multi core procs exist),
Each of these modes are optimised for different scenarios.
Generally, it’s best not to change these settings, and especially on the machine level.
The .NET 4.0 GC is considerably smarter than previous versions of the framework, and there is even less reason to contemplate changing it.
Before .NET 4.0 the GC on a concurrent workstation could do most but not all of gen 0 and gen 1 reclaim at the same time as the gen 2 items.
The GC was unable to start additional collections when a current collection was in progress.
This meant that only memory in the current segment or block could be reclaimed.
In .NET 4.0 background GC has been introduced
This allows another GC (gen 0 and 1) to start at the same time as an existing full GC (gen 0, 1 and 2) is running.
This is able to significantly reduce the time a full GC takes.
Concurrent workstation GC has been replaced by background GC.
Server modes currently don’t support the background GC, but the CLR team is aiming to have this introduced in the next version of the framework.
GC in .NET 4.0 has been tested on machines with up to 128 CPU cores, with confirmed efficiency improvements.
Apparently they’ve reduced the time needed to suspend managed threads.
A couple of good informative links on background GC
Garbage Collection Notifications
In .NET 3.5SP1 onwards we’re provided with GC.RegisterForFullGCNotification.
Only available when concurrent GC is disabled (not the default).
Does not support concurrent garbage collection because memory allocations are allowed while concurrent garbage collection is in progress. See the <gcConcurrent> runtime setting for information about how to disable concurrent garbage collection.
Have a look at this example Microsoft has provided for Garbage Collection Notifications.
I’m not sure why MS has decided to implement notifications this way.
I would have thought a much better way to do this would be to simply subscribe to a notification event providing a delegate with WaitForFullGCProc (your conditional logic), rather than spin up a new thread which takes a ThreadStart delegate of WaitForFullGCProc (your conditional logic) and blocks on GC.WaitForFullGCApproach.
Thoughts / Feedback welcome.