Gergely Kalapos

GC Flavors in .NET

Posted on January 17, 2015

Since I have to look up these things at least twice a year I decided to write an extremely compressed summary about the GC types/settings in the .NET framework.

Warning: In order to deeply understand this topic look for a longer and deeper article (or even for a book). This is here just a refresher about the specific settings in .NET.

  1. Workstation GC: 
    -The default on non apps (like WPF, Console Application, etc…) 
    -GC is done by a single thread (only 1 thread!)

    1.1 Concurrent Workstation GC
         -Special Thread created by the CLR
         -The GC thread runs concurrently with the other application threads most of the time, but occasionally it suspends all the other application threads for a short time)

    -1.2 Non-Concurrent Workstation GC:
        -There is no special GC thread. An application thread is picked by the GC and it does the job in this thread. In this case for any GC activity all the other threads must be suspended. Today there is no reason to use this. (or at least I don’t see any..)

  2. Server GC:
    -There are multiple GC threads. (makes sense, because garbage collection algorithms can be parallelised very well)

    2.1 Before .NET 4.5 (Non-Concurrent Server GC):
      -There was no concurrent version of Server GC (meaning every application thread was blocked during GC -> introduced delays, but the garbage collection itself was still faster then in a Workstation GC, since the GC algorithm itself run in parallel)
    2.2 After .NET 4.5 (Concurrent Server GC):
       -Multiple, dedicated GC threads. This one is kind of the “Best of both worlds” solution

Some facts: 

  • You cannot change flavors at runtime (But there is a LatencyMode property on GCSettings, since .NET 3.5. With that you still cannot switch from workstation to server GC, but in some cases can be very helpful. See here! - Thanks for Allon Guralnek for the comment!)
  • Currently the .NET profiling API cannot deal with blocking GC, meaning when you attach a profiler to your application then it forces the application to start with a non-concurrent GC.
  • You can configure it in the App.config under runtime, where invalid combinations are ignored (like concurrent server GC under CLR 2)
    <!--?xml version="1.0" encoding="utf-8" ?-->
       <gcConcurrent enabled="true|false"></gcConcurrent>
       <gcServer enabled="true|false"></gcServer>