From C# To Perl: Garbage Collection

2011-02-19

I don’t think that it is a stretch to say that every modern language that isn’t built especially for peformance or system programming uses a garbage collector. The programmer productivity gains that you get by lifting the burden of manual memory management can be large. Sure, you lose some control, but most tasks don’t require that level of control. C/C++ is always there if by chance you actually do. With that being said, let’s look at how the Perl and C# garbage collectors compare.

Perl employs a simple reference counting garbage collector. A reference counting garbage collector works exactly as the name implies. It keeps a count of the number of references to a piece of data on the heap. When the number of references to an object reaches zero the collector knows that it can reclaim the data. The major limitation of this algorithm is that it cannot handle circular references because the reference count will never reach zero. Even if your application can no longer access the data, the collector will never reclaim it, leading to a memory leak. Fortunately, circular data structures don’t come up in most applications, but you must be aware when they do. Perl allows you to get around this by weakening a reference. A reference that has been weakened does not increment the reference count for the garbage collector, allowing the it to reclaim circular data structures when used properly.

Coming from C# the simplicity of the Perl garbage collector was a bit of a surprise, because, quite frankly, I find the .NET garbage collector to be amazing. It uses generational collection, allowing for faster collection cycles that get most objects, with periodic longer collections to check older generations. The longer collection cycles use a simple mark and sweep algorithm. There are even different modes depending on if you have a desktop or web application. It also allows you to weaken references, manage non-memory resources with finalizers (although you should be implementing the IDisposable pattern), induce collections, or get notifications when the runtime senses a full garbage collection is approaching. This is a massive topic, but if you want to learn more about .NET garbage collection then you ever wanted to, a good place to start is the blog of Maoni Stephens, who spends her days actually working on it.

Put simply, C# collector puts Perl’s to shame. Unfortunately, the programming language shootout uses the Mono implementation of C#, so a quick comparison against Perl isn’t feasible. Quick benchmarks most likely won’t exercise the generational collector very well anyways. If Perl 6 ever gets around to being ready (I’m not counting on it), Parrot will allow for pluggable garbage collection engines. I would fully expect for something better than the current Perl 5 garbage collector to be an option. For now though, C# has a clear edge.