Memory leak with Castle.Core ProxyGenerator

After investigating why our web app had rapidly rising memory consumption even with fairly low traffic after some simple changes, we found that creating a new ProxyGenerator for every time a service was invoked was the culprit.

Graph from Stackify showing memory consumption rise rapidly
Ever-rising memory consumption is scary. This is from our Stackify monitoring after the unfortunate change was deployed into production.

After investigating why our web app had rapidly rising memory consumption even with fairly low traffic after some simple changes, we found that creating a new ProxyGenerator for every time a service was invoked was the culprit.

We were using the ProxyGenerator to dynamically create a proxy class to enable interceptors from Castle.Windsor to be used along with the (now deprecated) StructureMap IOC-container.

Simply moving the ProxyGenerator to a static field outside the method which actually creates the proxy, instead of making a new one every time fixed it. This was suggested here and here as well, with the reason being that it'll reuse already generated types if you only have a single instance.

I wanted some hard numbers though, so I made this tiny test-application, to try it out. And the results speak well for themselves, shown below. It's a pretty major performance hit. And the larger your volume, the larger the hit; not just memory consumption as first seen.

Using the locally created, always new and fresh ProxyGenerator, this is the result:

Creating 3000 proxies took 19394 milliseconds, and consumes about 192 MB of memory.
19 394 milliseconds and around 192 MB of memory consumed.

Using a static field does the same way faster and with way less memory consumed:

Creating 3000 proxies took 142 milliseconds, and consumes about 14 MB of memory.
142 milliseconds and around 14 MB of memory consumed(!) for the exact same job.