SGen: Mono’s Generational Garbage Collector
While Mono has in general been doing an admirable job of keeping up with .NET when it comes to APIs, there is one critical area where it is still far behind. The default garbage collector in Mono is the portable but inaccurate Boehm-Demers-Weiser conservative garbage collector. The main problem with the Boehm garbage collector is that it cannot accurately read registers and stack frames. Since it cannot determine if a given value is a pointer or a scalar, it always assumes that it is a pointer and marks the associated object as still alive. Not only can this incorrectly prevent large chunks of memory from being collected, it also makes compacting free space difficult.
SGen or “Simple Generational” is Mono’s new garbage collector. As the name implies, this two-year-old project is an attempt to replace Mono’s original garbage collector with a precise generational garbage collector similar to what we see in the .NET version of the CLR. The SGen garbage collector uses two generations instead of .NET’s three, but like .NET does have a separate heap for large objects.
Before Mono 2.10, which is still in preview, SGen was still very conservative. This new version adds support precise collection of managed stack frames, making it far less likely to encounter false positives. Unmanaged stack frames arising from p/invoke calls are still scanned conservatively.
Like .NET, SGen’s biggest weakness is pinned objects. If you pin an object in SGen’s nursery (think generation 0 in .NET), then it cannot completely clear out the nursery and memory becomes fragmented. The problem is actually worse in SGen for a couple of reasons. Not only are you dealing with fragmentation, it is fragmentation in the generation that SGen allocates memory from. Ideally all active objects are copied out of the nursery and it is reused whole cloth.
To compound matters SGen doesn’t just pay attention to explicit pins like .NET. As we mentioned before, the conservative scanning of unmanaged stack frames can cause objects to be pinned merely because there is a numeric value in the stack that happens to match a memory address in the nursery. Presumably this will be fixed in future versions as the pinning logic associated with p/invoke calls become more reliable.
Great to see generational GC
Is this a good or bad idea ???