In recent days, in one of my projects, we found an innocently looking bug that was a little too overweight – sometimes weighing more than 6GB in size in a 8GB web server. Well, a memory leak that caused the application pool to crash by exhausting the system memory. So I thought that, why not share it here so that if anyone else, facing the same problem, can get some insight. Here goes the plot –
The main goal of the project was to build a modular framework to be used to build robust web applications easily. For that reason the most obvious choice was to use Inversion of Control Pattern.
If you are already here then it is highly normal that you are familiar with the IOC( Inversion of Control) pattern already, but if you are not, then here is a good article for you.
As you all know, castle windsor is a widely used service locator library we used it for our IOC implementation. Therefore, we registered our services like this –
If you are new to castle windsor and the life cycle of the items it resolves, grab its details from here.
In short, LifestyleType.Transient means each time you ask castle windsor to resolve or give you an instance of an interface it will create a new one each time. But the default implementation of castle windsor with transient life cycle does the following –
- It creates a new instance each time ask for
- Keeps a reference of that instance created, so that it can refer it later
- Assumes that you will release the instance manually, again remember it, manually.
The first two options is not a problem, but the third one is a possible leak. If in any case you do not release the instance manually its a never-ending memory leak. Because the default garbage collector of CLR will never clear it since castle windsor is holding a reference and castle will never clear it because it thinks you will clear it yourself. That’s what we exactly did and well it took only 2 hours to consume all the server memory (6GB +) and crash it.
If you are interested about the possible memory management scenarios, see this article here, I realized our problem reading this one.
Well, now comes the big question – Whats the easiest solution?
Well you can release all the instance manually that you resolved using castle windsor or you can grab the solution mention here.
I will save your time. Just in the castle service locator where you are creating the kernel, add the following lines –
_container.Kernel.ReleasePolicy = new NoTrackingReleasePolicy();
Basically what it does is that, it prevents castle windsor from keeping any references of resolved instances and thus when you are done with your code and the object needs releasing the default GC collects it and the memory is freed. Which removed the memory leak problem. And you know what now the memory consumption never goes over 600MB. 🙂
It’s highly usual that you are using NHibernate with castle windsor and you think NHibernate is causing the leak?.. well don’t be harsh on NHibernate ; its castle and your unreleased instances, who is causing the leak. 😀