The Importance Of Releasing Your Components Through Windsor

13 commentsWritten on December 13th, 2008 by
Categories: Castle Windsor, Memory Management

We ran into a huge memory leak this week. A bit of memory profiling with JetBrains' dotTrace quickly showed that the Windsor IoC container was holding on to a lot of references. It turned out that i actually forgot to release the components i was requesting Windsor to construct for me. I use the container in my web-layer to compose every page's Controller with its dependencies. And in my service layer, i use the container to compose every RequestHandler and its dependencies. So that's two instances of the Container, in two separate AppDomains, and both are leaking a lot of memory due to my mistake.

My mistake was that after i was done with the components that i asked Windsor to resolve, i simply disposed them (which in turn would dispose their dependencies) and i figured that would be enough, since my components are registered as Transient. That means that each time you request a Transient component, you get a new instance. This led me to believe that Windsor wouldn't need to hold a reference to the constructed components so i figured that simply disposing them would be enough, since they are IDisposables. Disposing them is a good thing obviously, but because the container was still holding references to the requested components, that's still a lot of memory that is being wasted because even though you've disposed them, they aren't eligible for Garbage Collection until they are no longer accessible. And because the container kept references to them, they remained accessible and were never collected. And there was my memory leak. Oops.

In order to prevent this problem in the future for myself and anyone else who reads this, let's go over a few examples which should make it clear how you should make sure that your components are properly released so they are eligible for garbage collection.

Let's start really simple. We have an IController interface and a simple Controller class which implements the IController interface:

    public interface IController : IDisposable

    {

        bool Disposed { get; set; }

    }

 

    public class Controller : IController

    {

        public void Dispose()

        {

            Disposed = true;

        }

 

        public bool Disposed { get; set; }

    }

In our tests, we'll use the following method to create and configure the container:

        private WindsorContainer CreateContainer()

        {

            var container = new WindsorContainer();

            container.Register(Component.For<IController>().ImplementedBy<Controller>().LifeStyle.Transient);

            return container;

        }

The IController interface is registered with the container, and the container will return a new Controller instance (because of the Transient lifestyle) whenever someone requests an IController instance.

The following test highlights the memory leak that i was experiencing:

        [Test]

        public void ContainerKeepsReferenceToControllerIfWeOnlyDisposeOfIt()

        {

            var container = CreateContainer();

            var controller = container.Resolve<IController>();

            Assert.That(container.Kernel.ReleasePolicy.HasTrack(controller));

            controller.Dispose();

            Assert.IsTrue(controller.Disposed);

            // the controller is disposed of, but the container is still keeping track

            // of the instance

            Assert.That(container.Kernel.ReleasePolicy.HasTrack(controller));

        }

When you request a component from the Container, it keeps a reference to that instance in its Kernel's ReleasePolicy object. If you merely dispose of your requested component, the ReleasePolicy still holds the reference to the component. This is what caused my memory leak.

So how do we avoid this problem? It's pretty easy actually:

        [Test]

        public void ContainerDoesNotKeepReferenceToControllerIfWeReleaseIt()

        {

            var container = CreateContainer();

            var controller = container.Resolve<IController>();

            Assert.That(container.Kernel.ReleasePolicy.HasTrack(controller));

            // instead of disposing the controller, we'll Release it through the container

            container.Release(controller);

            Assert.IsTrue(controller.Disposed);

            // the controller is disposed of, and the container is no longer keeping

            // track of the instance

            Assert.IsFalse(container.Kernel.ReleasePolicy.HasTrack(controller));

        }

Instead of just disposing our controller, we tell the container to release it. The container in turn knows that because IController inherits from IDisposable, it should dispose the Controller instance. It also removes the instance from its Kernel's ReleasePolicy object and once your own reference to the Controller instance goes out of scope, it's eligible to be collected by the Garbage Collector.

As you can see, it's very easy to make sure your components are properly released and eligible for garbage collection. But what about possible dependencies of your components? Let's take a look.

Suppose we define the following interface and implementation:

    public interface IDependency { }

 

    public class MyDependency : IDependency { }

The dependency doesn't actually do anything, but bear with me :)

We modify the IController interface and Controller implementation like this:

    public interface IController : IDisposable

    {

        bool Disposed { get; set; }

        IDependency Dependency { get; }

    }

 

    public class Controller : IController

    {

        public IDependency Dependency { get; private set; }

 

        public Controller(IDependency myDependency)

        {

            Dependency = myDependency;

        }

 

        public void Dispose()

        {

            Disposed = true;

        }

 

        public bool Disposed { get; set; }

    }

And then we modify the configuration of the container like this:

        private WindsorContainer CreateContainer()

        {

            var container = new WindsorContainer();

            container.Register(Component.For<IController>().ImplementedBy<Controller>().LifeStyle.Transient);

            container.Register(Component.For<IDependency>().ImplementedBy<MyDependency>().LifeStyle.Transient);

            return container;

        }

Whenever we request an IController instance, the container will construct a Controller instance and will pass a MyDependency instance to the Controller's instance constructor. The question now is: does the container also track the instances of a requested component's dependencies? The answer is: no

        [Test]

        public void ContainerDoesNotKeepReferenceToControllersDependencies()

        {

            var container = CreateContainer();

            var controller = container.Resolve<IController>();

            Assert.That(container.Kernel.ReleasePolicy.HasTrack(controller));

            Assert.IsFalse(container.Kernel.ReleasePolicy.HasTrack(controller.Dependency));

        }

We request an IController instance, which is tracked by the container. The IController's Dependency property contains an IDependency instance, which was also created by the container. But as the last line of the test shows: the container does not track instances of the requested IController's dependencies.

So what does that mean? If the dependencies don't require any cleanup, then this is great. We simply need to release the requested component, and the component and its dependencies will all be eligible for Garbage Collection.

(Note 27/01/10: the following part is no longer relevant as of Castle Windsor 2.1)

But what happens when the dependencies need to be disposed? Let's take another look.

We modify the IDependency interface and MyDependency class so it looks like this:

    public interface IDependency : IDisposable

    {

        bool Disposed { get; set; }

    }

 

    public class MyDependency : IDependency

    {

        public bool Disposed { get; set; }

 

        public void Dispose()

        {

            Disposed = true;

        }

    }

Now let's see what happens with the Controller's dependencies when we release the Controller:

        [Test]

        public void ContainerDoesNotDisposeControllersDisposableDependencies()

        {

            var container = CreateContainer();

            var controller = container.Resolve<IController>();

            var dependency = controller.Dependency;

            Assert.That(container.Kernel.ReleasePolicy.HasTrack(controller));

            container.Release(controller);

            Assert.IsFalse(container.Kernel.ReleasePolicy.HasTrack(controller));          

            Assert.IsFalse(container.Kernel.ReleasePolicy.HasTrack(dependency));

            Assert.IsTrue(controller.Disposed);

            Assert.IsFalse(dependency.Disposed);

        }

The container holds no references, but the Controller's Dependency instance is not disposed! Notice however that the Controller has been disposed by the container. As i've mentioned earlier, if you own a reference to an IDisposable instance, you are responsible for properly disposing of that instance. So we modify the Controller's Dispose method so that it looks like this:

        public void Dispose()

        {

            Dependency.Dispose();

            Disposed = true;

        }

The previous test will now fail, because the Dependency will be properly disposed.

NOTE: i certainly don't recommend to implement your Dispose methods like i just did. This is just a simplified example. The proper way to implement the Disposable Pattern is discussed here.

Anyways, i hope it's clear now how you can make sure your IoC usage does not cause memory leaks, and that everything is properly disposed of.

  • http://bartreyserhove.blogspot.com Bart Reyserhove

    Nice post Davy. Definitely something I’ll check on monday in our application ;-)

  • Pingback: The Inquisitive Coder - Davy Brion’s Blog » Blog Archive » The Component Burden

  • Pingback: Elegant Code » The Component Burden

  • Pingback: Reflective Perspective - Chris Alcock » The Morning Brew #244

  • Pingback: 2008 December 16 - Links for today « My (almost) Daily Links

  • Pingback: Elegant Code » The Resolvable

  • http://www.dynamisys.co.uk Richard Howells

    What version of Castle are you using? I downloaded RC3 (Sept 2007) which seems to be the latest on the site. Your container.Register code will nto compile for me. No Register method.


    var container = new WindsorContainer();

    container.Register(... // <---- I have no register method.

  • http://davybrion.com Davy Brion

    i always grab the latest trunk actually :)

  • http://dotnet.uni.lodz.pl/whut Whut

    You probably should mention that this behavior show itself only if given component implements IDisposable. If not there is no need to call container.Release()


    public interface IMyComponent { }

    [TestMethod]
    public void ContainerDoesntKeepReferenceToNotDisposableComponent()
    {
    var container = CreateContainer();
    var myComponent = container.Resolve();
    Assert.IsFalse(container.Kernel.ReleasePolicy.HasTrack(myComponent));
    }

  • Morten Jacobsen

    I am trying to integrate some of your posts on Castle Windsor and NHibernate, when I ran into a problem.. Being new to both technologies, forgive me if this seems obvious :) ..

    From this post, it seems that whenever I use Container.Resolve() on a type that implements IDisposable, then I should not use the returned instance in a using statement, but rather wrap it in a try-catch-finally block so I always call Container.Release ?

    But in your post about managing NHibernate sessions (http://davybrion.com/blog/2008/06/managing-your-nhibernate-sessions/) you have the following code:

    public ProductCategoryDTO[] GetAllProductCategories()
    {
    using (Container.Resolve())
    {
    var repository = Container.Resolve();
    var categories = repository.GetAllProductCategories();
    return categories.ToDTOs();
    }
    }

    Now my question is this: is this not “wrong” according the information of this post? Doesn’t this mean that the IUnitOfWork instance will never be released from the container since it implements IDispoable?

    If so, how would you handle this properly?

    Thanks in advance,
    Morten Jacobsen

  • http://davybrion.com Davy Brion

    That example would indeed cause a problem with the resolved IUnitOfWork instance not being released through the container

    In our code at work, that’s not a problem because we never resolve the IUnitOfWork directly, and it’s always used as a dependency of a resolved component (a Request Handler). That resolved component is always released through the container.

    You can also avoid the problem like this:
    http://davybrion.com/blog/2008/12/the-resolvable/

  • http://kozmic.pl Krzysztof Koźmic

    Davy,

    I would like to bring this to your attention, that the behavior you’re describing was actually a bug, and it is fixed in current version (v2.1)
    Since your post is pretty high in search engines, I think it might beneficial to put a notification about it on top of the post, to avoid confusing people seeking information about how that works in current version.

  • Pingback: The Resolvable