Munq is for web, Unity is for Enterprise

The Unity Application Block (Unity) is a lightweight extensible dependency injection container with support for constructor, property, and method call injection. It’s a great library for facilitating Inversion of Control and the recent version supports AOP as well. However, when it comes to performance, it’s CPU hungry. In fact it’s so CPU hungry that it makes it impossible to make it work at Internet Scale. I was investigating some CPU issue on a portal that gets around 3MM hits per day and I found unusually high CPU. Here’s why:

Unity_High_CPU

I did some CPU profiling on my open source project Dropthings and found that the highest CPU is consumed by Unity’s Resolve<>(). There’s no funky use of Unity in the project. Straightforward Register<>() and Resolve<>(). But as you can see, Resolve<>() is consuming significantly high CPU even after the site is warm and has been running for a while.

Then I tried Munq, which is a basic Dependency Injection Container. It has everything you will usually need in a regular project. It boasts to be the fastest DI out there. So, I converted all Unity code to Munq in Dropthings and did a CPU profile and Whala!

MunqMuchBetter

 

There’s no trace of any Munq calls anywhere. That proves Munq is a lot faster than Unity.

21 Comments

    • The CPU graph is from my PC. So, that’s not how the server looks like. The important thing to notice is in the list of “Functions that does most work”, Unity is no longer there. A Container should not be the function doing most of the work.

  1. Omar, I was curious to know your opinion about Spring.Net – as a DI framework. Did you try this..? if so..what do you think about it’s performance comparing Munq/Unity…?

    Thanks.

  2. I agree with your comment that Munq vs Unity. However, your CPU is at 20% – 40%. Was CPU the bottleneck? Or is RAM, network or disk the bottleneck? Also, what very of Unity where you using?

    • That’s CPU graph on my PC, not on the server. I am doing profiling on my PC because you can’t run CPU profile on a production server getting hundreds of hits per second.
      Using Unity 2.0

  3. I’m glad you’ve found Munq to meet your requirements. Munq was built from the ground up, based on what I learned helping Daniel Cazzulino speed up Funq.
    Where Funq is focused on the mobile app space, Munq, and particularily the Lifetime Management, is focused on the Web app space.
    Are you using the release verions, or the latest source code. The latest source, while no faster, is a little more robust (tested) and has a few extra features. The only thing keeping me from releasing it is finding the time to update the documentation.
    Since I’m giving a presentation on Munq to my team mates at The Code Project this week, I expect to release soon.

    • Great, looking forward to a new release.

      Some requests:

      I had to tweak the code to make RequestLifetime work with standard ASP.NET. It works with ASP.NET MVC only. Could you offer both please?

      For registering a Lazy Get, I did this:
      public static IRegistration RegisterTypeForLazyGet(Func register)
      {
      Func lazyResolve = () => register(_container);
      return _container.RegisterInstance>(lazyResolve);
      }

      This registers the lazyResolve Func as an instance, instead of a type. Thus it prevents a new instance of this laxyResolve func from getting created everytime Resolve is called. Can you please incorporate this in the latest code? Current Lazy Resolve creating a new Func first and then calling it, instead of reusing the same func.

  4. I’ve taken a quick look at your code. You can gain some more performance benefits if you use RequestLifetime for some of the classes, such as your repositories and IDatabase. Anything that a single instance could service a request could use this. This causes the same instance to returned for a Resolve() in the same Request, but different for different Requests.

    • Good observation. I am doing this by preserving the instance of Facade at the request level. Since the Facade contains reference to all Repositories and IDatabase, all of them are now being ‘instance pooled’ because Facade is getting stored at Request context inside Global.asax. I just need to update code everywhere on the UI layer to resolve the Facade by calling Service.Get<> instead of creating a new Facade everytime.

  5. What was the issue you were having with RequestLifetime in ASP.NET Forms? I don’t seem to have a problem, but then I’m working with newer code.

    Your question about the LazyResolve has given me an idea that may actually speed up Resolution.

  6. Hi Omar
    May be you made not right conclusion. As i saw average CPU usage in the second test is more than in the first test.
    May be there is a lot of calls of Resolve in the first test those incapsulates other calls. But in the second test Monq delegates calls (incapsulated by Unity`s Resolve) to other methods those take CPU consumption.
    What do you think?

    • The two tests weren’t exactly identical. As I have done it manually, just refreshing page, clicking here and there, the speed of my actions performed in the two steps varied and thus the average CPU was different.

      But both tests did hit the Container calls several hundred times. What we see from the report is that the Container calls are no longer the most expensive operations any more.

Leave a Reply