Reputation: 65411
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
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
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
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
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
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