I ran into a problem where my program would run out of memory when using Castle Windsor and interceptors. It's reproducible using the following code:
public interface ITest{}
public class Test : ITest {}
class TestInterceptor:IInterceptor {
public void Intercept(IInvocation invocation) {}
}
class Program {
static void Main(string[] args) {
while(true) {
using(var container = new WindsorContainer()) {
container.Register(Component.For<TestInterceptor>());
container.Register(Component.
For<ITest>().
ImplementedBy<Test>().
Interceptors(
InterceptorReference.ForType<TestInterceptor>()
).Anywhere);
var tst = container.Resolve<ITest>();
}
}
}
}
This is how memory usage develops:
So the thing that threw me off was that I thought there was a non-managed code memory leak, but after a lot of debugging I found out the problem was with the interceptor prxoy generation: a new (dynamic) assembly with a proxy type is introduced to the runtime everytime it's resolved:
Now, I guess you can solve this by
- using a global (static) container for the entire app, but at the moment this is not feasible for my app (I read this is the preferred way of doing this, not entirely clear why)
- generating the proxy yourself using a static
ProxyGenerator
and using theUsingFactoryMethod
way of producing an instance (which I do now)
This leaves me to 3 questions:
- Am I using Castle Windsor correctly (docs are not entirely clear) and if so is there a way for Castle Windsor to cache the proxy type?
- Should Castle Windsor cache the proxy type automatically (or: is the current behavior a bug)?
- How would you debug (using perfmon, for example) that dynamically generated assemblies are eating all your memory?
Thank you.