1
Vote

UnityContainer Pipeline Behavior when using Interception

description

Our recent application deployed to production is facing performance issue and users are revoked access because of the same. It’s observed that application response time is degrading quite often and sometime IIS application is crashing as well. Microsoft has provided an analysis to indicate that our application Service code has looping issue while using unity container framework.


We are facing issue related to Enterprise Library Unity Container. We maintain an application cache on our application server side for some entities (5 business entities). We have used unity container interception feature to intercept calls in our façade layer (data provider layer in application server) to decide whether the required entity exists in the cache or not. It has been observed in MS dump utility trace and in our application logs, that a huge number of calls are made to our CacheHandler that is configured with Unity framework for cached entities. This is causing stack overflow issue on the server and memory usage is growing as well very rapidly. This is resulting our IIS app(application service layer) to respond very slow or sometime even crashing the IIS app (w3wp.exe) completely.

After a code analysis and debugging it has been found out that we use httpmodule which is using a unity container instance. Httpmodule is used to handle “PostMapRquest” http pipeline event. In this event handler we create a new extension to the unity container each time a call made to the server. In the new extension we also do register our provider instances for interception along with the interceptor. On the cachehandler whenever we check for the entity we call the following method for going ahead with the next pipeline behavior

// Call the original method
result = getNext()(input, getNext);

As per our understanding the call above triggers the Unity pipeline and invokes each extension and behaviors underneath. This is causing more calls to our Cachehandler than expected. As the HttpModule lives as long as the IIS application lives , unity container is growing big whenever each call is made.

Solution:
We will not keep the instance of UnityContainer once the service call is executed. For each call we will instantiate a new unity container and just before the Post Map request event handler ends we will remove all extensions from the unity container and dispose the container.

// Clear all the extensions when application context is created.
this.unityContainer.RemoveAllExtensions();
this.unityContainer.Dispose();

We will also modify the code to restrict registering only one type of provider to UnityContainer for one time only. This will reduce the no of providers underneath and will reduce the cachehandler call within a single flow. We will follow Unity Config file to do the registration to avoid multiple registration. Please let us know your recommendation and let us also know if we are correct on our analysis.

comments

randylevy wrote Sep 12, 2016 at 6:33 PM

Hi,

The Unity project has been moved to github so you should probably post your issue there: https://github.com/unitycontainer/unity/issues . A scaled down repro of the issue might help as well.

However, here are some of my thoughts.

From your description the one thing that stands out to me is:

In this event handler we create a new extension to the unity container each time a call made to the server.

This seems like a very atypical usage. Usually, a container extension is added once at container creation time. Given that if you use one container and extension per request (and dispose at the end of the request) then everything is OK, it seems to me, without looking at any code, that multiple container extension registrations might be causing some issues (e.g multiple registrations or circular references).

I'm going to guess that the reason you register an extension per request is that you need to populate (and use) per request information (or at least lifetime) in the extension and perhaps the instantiated objects themselves. One typical approach to deal with that is to create a child container on every request.

The process is similar to what you are doing but should be more efficient:
  • On application start create the UnityContainer and register any "common" registrations (e.g. true singletons)
  • When a request comes in call container.CreateChildContainer() and register your extension
  • Resolve all objects from the child container
  • Dispose the child container at the end of the request