Shiraz Bhaiji
Shiraz Bhaiji

Reputation: 65411

Performance and use of Resolve in Unity

We use Unity as our IOC Container.

Our program is written so far in a way that we resolve an interface just before we need to use it.

This however results in the interface being resolved inside a loop. Which could result in the interface being resolved 100,000 times in one run.

Question is: Would moving the resolve outside the loop have a significant difference or is this just micro optimisation?

Our progrm takes over a day to run. So for those who will answer "test it yourself", it is actually faster to ask the question here :)

Upvotes: 2

Views: 6447

Answers (5)

Nick Rubino
Nick Rubino

Reputation: 1035

This Question is a little old but I found when using Unity, to improve performance I forced singleton, ContainerControlledLifetimeManager, instances (mentioned in Roels answer above) of any objects besides the Controllers. Controllers need to be new instances every time they are called. I used the following code in the Bootstrap.cs/RegisterTypes method that is called in the global.asax file.

var controllerClasses = AllClasses.FromLoadedAssemblies()
    .Where(t => t.FullName.Contains("Controller")).ToList();
var nonControllerClasses = AllClasses.FromLoadedAssemblies()
    .Where(t => !t.FullName.Contains("Controller")).ToList();

container.RegisterTypes(controllerClasses, WithMappings.FromMatchingInterface, WithName.Default);
container.RegisterTypes(nonControllerClasses, WithMappings.FromMatchingInterface, WithName.Default,
    type => new ContainerControlledLifetimeManager());

NOTE - You will want to make the where expressions on the code that populates the controllerClasses and nonControllerClasses more specific so that you only register the classes you need. IE filter by namespace.

Upvotes: 0

Myles McDonnell
Myles McDonnell

Reputation: 13335

I'm sure (or I hope!) resolve is optimized already, particularly in the case of container controlled instances (ContainerControlledLifetimeManager), which I'm assuming from the question you have here, but it stands to reason that calling it less will be less work than calling it more.

I put together a very naive test in which the resolve results are an order of magnitude slower, but not slow. Of course this doesn't take into consideration what else might be registered with the container, or number of instances being managed, or what is being instantiated, or any number of other factors I have missed. IMHO the only way to really answer your question is to test your app, sorry :(

RESULTS:
00:00:00.2462702 : Resolve ContainerControlledLifetimeManager
00:00:00.0014184 : Plain assignment
00:00:00.3514334 : Resolve PerResolveLifetimeManager 
00:00:00.0019258 : Direct instantiation


class Program
{
    static readonly IUnityContainer _container = new UnityContainer();

    static void Main(string[] args)
    {
        _container.RegisterType(typeof(IInterfaceOne), typeof (ClassOne), new ContainerControlledLifetimeManager());
        _container.RegisterType(typeof(IInterfaceTwo), typeof(ClassTwo), new PerResolveLifetimeManager());

        var classOne = new ClassOne();

        DoLots("Resolve ContainerControlledLifetimeManager", ()=>_container.Resolve<IInterfaceOne>());
        DoLots("Plain assignment", () =>classOne);

        DoLots("Resolve PerResolveLifetimeManager ", () => _container.Resolve<IInterfaceTwo>());
        DoLots("Direct instantiation", () => new ClassTwo());

        Console.ReadLine();
    }

    static void DoLots(string msg, Func<object> resolveFunc)
    {
        var stopwatch = new Stopwatch();
        stopwatch.Start();
        for (int i = 0; i < 100000; i++)
        {
            var instance = resolveFunc();
        }
        stopwatch.Stop();

        Console.WriteLine(string.Format("{0} : {1}",stopwatch.Elapsed , msg ));
    }
}

public interface IInterfaceOne{}
public interface IInterfaceTwo{}

public class ClassOne : IInterfaceOne{}
public class ClassTwo : IInterfaceTwo{}

Upvotes: 1

Alexey Raga
Alexey Raga

Reputation: 7525

I don't quite understand what do you mean by resolving 100,000 times withing the loop... If you DO want to resolve 100,000 times then it does not matter whether you are doing it in a loop or not, speed is going to be the same.

I would recommend you to check if you can reuse instances that have already been resolved...

Again, no one but you can tell if your problems with speed are caused by the container. We don't know what you are doing within that loop of 100,000 iterations and it might be very possible that the overhead of resolving interfaces if <1% of the time you spend within the loop itself. Don't wait for a day, run it on just 1000 iterations and you will see...

Also you don't need to run your business logic, just implement a similar loop and only resolve your interfaces there, so you can see how much impact Unity has on your application.

But anyway, 100,000 resolves in more than 1 day means ~2 a second... It would take an effect, but not THAT dramatic... I would rather look what you can optimize in your business logic, or paralellize your loop.

Also Unity does not have a reputation of the fastest container ever (in fact it is quite opposite) ;) You can try Autofac which is significantly faster...

Here are some performance benchmarks for IoC containers.

Upvotes: 1

jgauffin
jgauffin

Reputation: 101150

It will of course affect performance. How much depends on the complexity of the dependency graph that the constructed object has and if any resources (such as db connections etc) are constructed too.

As Unity goes, it's not the fastest nor the slowest container around. Just about average.

Service location (using Resolve instead of constructor injection) is by many considered as an anti-pattern. The reason is that it's so easy to misuse it and that it hides dependencies as implementation details (instead of documenting the dependencies in the constructor).

Upvotes: 1

RoelF
RoelF

Reputation: 7573

It depends on how you registered the interface I would say. With which LifetimeManager did you register it?
Does your program always need a new instance? Or can it be the same instance over and over?

If you need the same instance (Singleton), use the ContainerControlledLifetimeManager:

Container.RegisterType<Interface, Implementation>(new ContainerControlledLifetimeManager());

If you don't care about which instance you get (new or old, maintained by GC), you can use ExternallyControlledLifeTimeManager:

Container.RegisterType<Interface, Implementation>(new ExternallyControlledLifeTimeManager());

You can also create your own implementation of a LifetimeManager to better fit your needs.

Take a look at this article about LifetimeManagers

Upvotes: 4

Related Questions