Note that there are some explanatory texts on larger screens.

plurals
  1. POAutofac resolving a singleton creates a bottleneck
    primarykey
    data
    text
    <p>I'm using Autofac in an asp.net MVC app and came across a problem with locking. Anytime a service depends on a singleton, that service is resolved from the root lifetime scope. This is because Autofac:</p> <ul> <li>resolves singleton components from the root scope</li> <li>resolves any components from the root scope who have dependencies that must be resolved from root.</li> </ul> <p>Further, when resolving from any scope, Autofac locks that scope. I think these are fine design decisions. My problem is with misbehaving classes who depend on singletons <strong>and</strong> have slow constructors. These create a bottleneck for anyone else needing to resolve a singleton. </p> <p>Since this is in a MVC app, each request is getting mapped to some MVC controller that's constructor injected. Further, most of my controllers take dependencies on various singleton services (logging, caching, etc). </p> <p>For things with fast constructors this is not a problem. But as soon as one poorly written class is requested, my throughput tanks because every new request is blocked on that misbehaving constructor. For example:</p> <p><strong>given these 3 classes</strong></p> <pre><code>//registered as SingleInstance() class MySingleton {} class BadTransient { public BadTransient(MySingleton s) { Thread.Sleep(5000); } } class FriendlyTransient {} </code></pre> <p><strong>resolved like</strong></p> <pre><code>using(var scope = container.BeginLifetimeScope("nested scope")) { //resolves from child scope var myFriend = scope.Resolve&lt;FriendlyTransient&gt;(); //resolves from root because it's a singleton var singleton = scope.Resolve&lt;MySingleton&gt;(); //resolves from root because it has a singleton dependency. //**** this locks the root scope for 5 seconds //**** no one else can resolve singletons. var troublemaker = scope.Resolve&lt;BadTransient&gt;(); } </code></pre> <p><strong>Is there a way I can avoid this bottleneck?</strong></p> <p>The obvious answer is to have fast constructors. The reality is that not all the constructors in my codebase can be guaranteed to be fast. There's <em>a lot</em> of legacy code, there's lots of code that relies on 3rd party code, there's code that looks fast but depends on code that isn't, there's code that's usually fast but breaks down in odd circumstances, etc. Educating developers only works to a certain extent. </p> <p>We've been fixing constructors as we find them, but I need a more proactive solution. It's not acceptable to let my users do my QA.</p> <p><em>Note: I don't care as much about slow constructors that don't depend on a singleton. They will lock their lifetime scope, but it won't block other threads</em></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload