EPiServer  /  CMS September 01, 2010

Something to beware of when using EPiAbstractions and an IoC container

I recently ran into a rather obscure but interesting problem on a project where we use EPiServer CMS, EPiAbstractions and Structure Map. At first, when the first request where made to the site after a release the site worked as expected but after having been up and running for a few minutes it started to feel less responsive and it gradually got worse. After about an hour it pretty much stopped responding. A quick look at the task managers performance tab showed the CPU usage at a 100%. In other words it behaved very much as if it had a memory leak, only it was a… CPU leak.

We profiled the application on a test server using dotTrace but at first we didn’t find anything that looked to be the cause of this problem. No method calls took an unreasonably long time to exectute or anything like that. However, after a while we noticed that there where a few methods that were called A LOT. Namely EPiAbstractions.DataFactoryFacade’s OnLoadingPage and OnLoadedPage were called 255 million times in just our profiling session which sampled me clicking around on the site for a few minutes.

As anyone who attended last weeks EPiServer user group meeting in Stockholm might recall from Stefan Forsberg’s presentation Structure Map uses a class’ most greedy constructor by default. The PageRepository class in EPiAbstraction, which we use extensively in our project, has two constructors:

public PageRepository(IDataFactoryFacade dataFactoryFacade, 
    IFilterForVisitorFacade filterForVisitorFacade)
{
    dataFactory = dataFactoryFacade;
    filterForVisitor = filterForVisitorFacade;
}

public PageRepository()
    : this (DataFactoryFacade.Instance, 
            FilterForVisitorFacade.Instance) {}

The first constructor is primarily to enable testing and extendibility and requires it’s user to provide an implementation of, among other things, the IDataFactoryFacade interface. The other constructor has no parameters and passes the singleton implementations of EPiAbstractions default implementations on to the first constructor.

The DataFactoryFacade class is a complete wrapper for EPiServer’s DataFactory class that enables us to work against an interface that resembles DataFactory’s but that we can isolate our code from. As such it has all of the events that DataFactory has and in order to facilitate that it’s constructor will add some of the class’ own methods as event handlers to DataFactory’s events when executed. Below is a very shortened version of the class that illustrates this.

public class DataFactoryFacade : IDataFactoryFacade
{
    public DataFactoryFacade()
    {
        DataFactory.Instance.LoadingPage += OnLoadingPage;
    }

    public event PageEventHandler LoadingPage;

    public virtual void OnLoadingPage(Object sender, PageEventArgs e)
    {
        if (LoadingPage != null)
            LoadingPage(sender, e);
    }
}

So, with this in mind, what will happen each time we request an instance of the IPageRepository interface from our container if we have configured our container with the default conventions? It will create a new instance of the PageRepository class using it’s most greedy constructor. That will in turn require the container to create a new instance of the DataFactoryFacade class which will add event handlers to DataFactory’s events. I’m guessing that we requested an IPageRepository from the container about ten to thirty times per HTTP request in this site so for each HTTP request a lot of new handlers where added to DataFactory’s events. Since DataFactory is a singleton that is never disposed of if will keep those pointers to the event handlers for ever and execute them every time one of the events, such as loading a page, occurred.

The fix? There are several ways to resolve this but we took the easy way and told Structure Map to treat IPageRepository as a singleton, returning the same instance of it for each request for it.

If you’ve read all the way down here about this obscure problem I applaud you! On the other hand odds are you are one of two persons named Stefan and Christian ;-)

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more

Comments

comments powered by Disqus

My book

Want a structured way to learn EPiServer 7 development? Check out my book on Leanpub!

More about EPiServer CMS