Ninject and performance
Asked Answered
I

3

9

I am doing a code review on a web site that will have a lot of simultaneous users, ca. 100,000 authenticated users.

I have found the following code of type:

    [Inject]
    public BusinessLayer.ILoginManager LoginManager { get; set; }

And in global.asax.cs:

   protected Ninject.IKernel CreateKernel()
    {
        return new StandardKernel(new ServiceModule());
    }


    internal class ServiceModule : NinjectModule
    {

        public override void Load()
        {
             Kernel.Bind<IReportProxy>().To<ReportProxy>().InRequestScope();
        }
    }

Question is: Will the use of Ninject affect performance? Are there situations in which you should not use Ninject due to performance?

Irrational answered 18/4, 2011 at 12:6 Comment(0)
M
7

As it always is with performance questions and issues, you cannot detect any of those just by looking at your code. Rather, profile your application and see where the problem is.

From my past experience, IoC containers only incur performance overhead on application startup and their impact is next to negligible while the app is running.

Marniemaro answered 18/4, 2011 at 12:11 Comment(1)
True, but all have varying APIs and feature sets. Consider making a decision based on a number of factors like API, support for target lifetimes (e.g. per web request is nice in web applications), performance for target usage, licensing, etc...Metametabel
V
4

Ninject caused us a lot of performance related grief on the project. It is one of the slowest DI out there and I would strongly recommend considering another DI engine (e.g. https://github.com/ninject/ninject/issues/84)

Couple of other things to note about Ninject:

  1. Unbind/Rebind are not thread safe (AFAIK not specified anywhere on the xmldocs). Symptom: intermittently you might loose some bindings due to duplicate key in Kenrel's internal dictionary.

  2. Referencing custom scope object from binding target could cause a memory leak (this one is actually reasonable but Ninject is in no way helpful in locating the issue). E.g. Bind an object that has a persistent reference to HttpContext in scope of HttpContext.Current

It is also worth keeping in mind that switching to a different DI might not be feasible depending on the feature set you would end up using (e.g. service location, conditional bindings, custom scopes, dynamic bindings etc.). Even if another DI framework has similar feature set (e.g. LightInject) syntax may be way too different.

Viscera answered 15/4, 2015 at 8:51 Comment(1)
I can highly recommend reviewing the bug link provided by @bushed. It leads to a great IoC performance benchmark for many frameworks.Marrow
M
1

I have stumbled across this question when I have noticed that a property injection (through [Inject] and kernel.Inject(instance) within a controller took about 3 seconds, thus delaying very much requests processing for a specific controller. Most of the other controllers were affected in a lesser degree.

Short answer

Yes, Ninject clearly brings an overhead, but I found to dependent on three factors: library version, dependency tree size and how dependency is solved.

Aim for a bigger version (3.3.4+), ensure that a dependency does not trigger lots of dependencies to be solved and that you use constructor injection rather than property injection.

Long answer

1. Injection pattern - I encountered performance issues when using property injection. A quick win was to replace it prop => kernel.Get<IFoo>(), but this pattern is not recommended (3.3.4 marks direct kernel usage as obsolete). However, it reduced the time required to solve the reference without performing major refactoring.

2. Dependency tree - my application used some generic repositories injected within a scoped data access which in turn was injected in several services. For some services this created a large dependency tree which required a lot of time to be solved. Reducing this tree greatly improved the performance.

3. Library version - I have upgraded the library from 3.2.0 to 3.3.4 and noticed a significant performance improvement. However, I payed the price of multiple changes inside the application (migrate from NinjectWebCommon to MvcApplication and upgrade of various libraries such as Castle.Core, Ninject.MockingKernel, Ninject.MockingKernel.NSubstitute, Ninject.Web.Common.WebHost)

Maisel answered 22/3, 2018 at 9:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.