There's been a discussion going on within DevelopMentor for a couple weeks regarding concurrent GC and when it really applies.
The idea behind the concurrent collector is to do as much of the GC while the UI thread continues to process UI stuff and then only interrupt the application threads when memory is being shuffled around and fixups are occurring. This provides for more responsive UI applications at the expense of slower collections and a higher memory utilization.
The instructors who are involved with .NET were discussing this because of a discrepancy in various reliable sources - First, Maoni Stephens, the ultimate authority on all things .NET GC, stated in her blog entries that concurrent GC was the default behavior for the workstation version of GC (see http://blogs.msdn.com/maoni for more information on this).
This is well known, and now well documented in various places. However, Jeff Richter seems to say in his book "CLR via C#" that concurrent collections occur only on multiprocessor machines. Several other authors back this up (notably Stephen Pratschner in "Customizing the .NET Framework Common Language Runtime" and Joe Duffy in his "Professional .NET Framework 2.0" book; both are excellent btw).
So, we had some differing opinions from people in the "know". Our Effective .NET and Essential .NET courses were written around Maoni's blogs and so the diagram we presented showed concurrent collections even on single-processor machines since she didn't explicitly say it required multiple processors to turn it on. One of the guys noticed this and said "Wait! That's wrong!"
We tried to actually see the concurrent collection in action but it turns out that it's actually quite difficult to get this to happen because concurrent collections only occur on Gen2, which for a well-written application shouldn't occur that often. To add to the complexity, the CLR attempts to optimize this behavior - just because it can do the GC concurrently, it might not. Finally, the thread which is used for this collection is actually created and destroy as necessary so it doesn't exist most of the time.
So, to settle the argument, Jason Whittington and I spent some time spelunking into the CLR this past week to see if we could spot the concurrent collection in action. With a little WinDBG and some symbols, I think we've put the question to rest once and for all (at least for us) . If you scan the GC symbols in mscorwks.dll, you'll find a treasure trove of information; one of the things that caught my eye was this:
0:000> x mscorwks!WKS::gcheap::* 79f8c5dd mscorwks!WKS::GCHeap::Relocate = <no type information> 7a0d09d9 mscorwks!WKS::GCHeap::ValidateObjectMember = <no type information> 7a088e2a mscorwks!WKS::GCHeap::IsConcurrentGCInProgress = <no type information>
0:000> u mscorwks!WKS::GCHeap::IsConcurrentGCInProgress mscorwks!WKS::GCHeap::IsConcurrentGCInProgress: 7a088e2a a1701b387a mov eax,dword ptr [mscorwks!WKS::gc_heap::settings+0x10 (7a381b70)] 7a088e2f c3 ret
0:000> bp mscorwks!WKS::GCHeap::RestartEE "j (dwo(mscorwks!WKS::GCHeap::GcCondemnedGeneration)==2) 'dd mscorwks!WKS::gc_heap::settings+0x10 L1';'g'"
0:000> u mscorwks!WKS::GCHeap::Initialize mscorwks!WKS::GCHeap::Initialize: 79ed6924 a14412387a mov eax,dword ptr [mscorwks!g_pConfig (7a381244)] 79ed6929 8b4058 mov eax,dword ptr [eax+58h] ..... 79ed697b 51 push ecx 79ed697c e823040000 call mscorwks!WKS::gc_heap::initialize_gc (79ed6da4) 79ed6981 85c0 test eax,eax
0:000> u mscorwks!WKS::gc_heap::initialize_gc mscorwks!WKS::gc_heap::initialize_gc: 79ed6da4 56 push esi 79ed6da5 e80cf1ffff call mscorwks!WKS::write_watch_api_supported (79ed5eb6) 79ed6daa 33f6 xor esi,esi ... 79ed6dc6 c70564ce387a01000000 mov dword ptr [mscorwks!WKS::gc_heap::gc_can_use_concurrent (7a38ce64)],1
0:000> dd mscorwks!WKS::gc_heap::gc_can_use_concurrent L1 7a38ce64 <b>00000001< span>b>
<xml version="1.0" encoding="utf-8" ?> <configuration> <runtime> <gcServer enabled="true" /> </< span>runtime> < span></configuration>
0:000> dd mscorwks!WKS::gc_heap::gc_can_use_concurrent L1 7a38ce64 <b>00000000< span>b>
It appears that the CLR is capable of doing concurrent collections on a single processor! My final test was to try turning it off altogether via a configuration switch:
<xml version="1.0" encoding="utf-8" ?> <configuration> <runtime> <gcConcurrent enabled="false" /> </< span>runtime> < span></configuration>
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.