Back when we were designing the new memory profiler last year, Andrew had realised that there was one thing that made all the exisiting memory profilers slow the profiled application to a crawl. That was remembering the place in the program (the call stack) that every object gets allocated. We’ve decided to take this feature out, not even including it as an option for v5.0, and here’s why.
Once upon a time, there were programming languages where you had to free all the memory that you allocated. If you didn’t, the memory would be lost forever, the traditional unmanaged code memory leak. So people thought of clever ways to make their code less prone to memory leaks. One of these was a principle that whichever piece of code allocated memory was also responsible to making sure it is freed when you’re finished with it.
This wasn’t a bad principle, and many good programs were written leak free because of it. Some programs got leaks though, so someone invented memory profilers. These were good because they would tell you where you had allocated the pieces of memory that weren’t freed. You could then fix the problem because it was always the code that allocated the memory that was responsible for freeing it.
Then one day (ok, so excuse my chronology, it’s been around for ages) someone invented garbage collection. Joy! We no longer had to worry about freeing memory, it was freed on its own when not referenced anymore. The old technique of copying data that needed to be passed became obselete, we could send our memory off into the distance, not knowing what adventures might be waiting for it.
But sometimes the data had misadventures. It might get referenced by something it shouldn’t do, end up in the wrong cache, and the managed memory leak was born. So managed memory profilers appeared. They were good because they told you where your memory was allocated, because it’s always the job of the code that allocates the memory to free… oh, wait, no it’s not!
The code that allocates memory has no responsibility over what happens to the memory, and usually has nothing to do with the code that leaks it.
So I think we’ve made a brave step, removing this age-old feature. Because it’s not actually useful.
Instead, what’s useful is knowing why your object is in memory still, and that’s all about what’s referencing it. In particular how it’s connected to GC roots. So that’s what we’ve tried to make the memory profiler v5 good for investigating (and I think if you try it you’ll agree, we succeeded). Also, it’s a gazillion times faster because it doesn’t have to hook into every object allocation.
The only trouble is, on rare occasions, allocation call stacks are useful. There is a (frankly horrible) system in .NET called the IDisposable pattern. It asks you to free (call Dispose() on) objects you’ve allocated. It’s necessary because .NET is built on top of the unmanaged world, where it’s important not to wait for the garbage collector before a resource is freed. I hate it, because it chains us back up to the technique of the piece of code that allocates an object having to dispose it. Maybe here allocation call stacks might be useful again. But because of finalizers, people are very rarely actually bitten when they forget to dispose things. Hopefully one day, everything will be designed so it can wait for the garbage collector before it gets freed, and the world will be a happier place.