I would like to confirm some questions about ModelBinderDictionary in asp.net mvc:
A single instance of ModelBinderDictionary is stored in ModelBinders.Binders static property. So during the whole application lifetime, we will have only one instance of ModelBinderDictionary.
But I found that ModelBinderDictionary is not thread-safe. What if two threads add model binders to ModelBinders.Binders at the same time (not in the Application_Start, but in some controller)?
I guess the reason why ModelBinderDictionary is not designed to be thread-safe is that ModelBinders.Binders is supposed to be accessed only in application start, so thread-safety is not needed because there'll be only one thread running in Application_Start, correct?
So if we are designing a class supposed to be accessed at any time, we have to make it thread-safe. Otherwise we don't need to guarantee thread-safty and simply do it like ModelBinderDictionary, correct?
So this is also about Trade-Off. Although adding model binders to ModelBinders.Binders at any time is allowed, but no one will do that. So we don't need to design for such rare case. That's why we don't guarantee thread-safety for ModelBinderDictionary, correct?
Related
I am using Simple Injector for my DI library. I have controllers in my asp.net MVC site that take services in their constructors via this library. When I look at the Diagnostic Tools in Visual Studio and see my Managed Memory I see multiple instances of the same service.
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterMvcIntegratedFilterProvider();
RegisterComponents(container);
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
My question is, is this by design. I figured one IPaymentsService would be used throughout all the controllers but I have a count of 187? I would think it should be 1.
I am thinking about adding the below line. Seems to be working fine, and now I see 700,000 KB less of memory used and a 10+ second faster load time on the site. Is there any downside with this?
container.Options.DefaultLifestyle = Lifestyle.Scoped;
Let me start with the basics, most of which you will likely be familiar with, but let’s do it for completeness and correctness.
With Simple Injector, Transient means short-lived and not cached. If service X is registered as Transient, and multiple components depend on X, each get their own new instance. Even if X implements IDisposable, it is not tracked nor disposed of. After creation, Simple Injector forgets about Transients immediately.
Within a specifically defined scope (e.g. a web request), Simple Injector will only create a single instance of a service registered as Scoped. If service X is Scoped, and multiple components depend on X, all components that are created within that same scope get the same instance of X. Scoped instances are tracked and if they implement IDisposable (or IAsyncDisposable), Simple Injector calls their Dispose method when the scope is disposed of. In the context of a web request disposal of scopes (and therefore Scoped components) this managed for you by the Simple Injector integration packages.
With Singleton, Simple injector will ensure at most one instance of that service within a single Container instances. If you have multiple Container instances (which you typically wouldn’t in production, but more likely during testing) each Container instance gets its own cache with Singletons.
The described behavior is specific to Simple Injector. Other DI Containers might have different behavior and definitions when it comes to these lifestyles:
Simple Injector considers a Transient component short lived, possibly including state, while the ASP.NET Core DI (MS.DI) considers Transient components to be *stateless, living for any possible duration. * Because of this different view, with MS.DI, Transients can be injected into Singletons, while with Simple Injector you can’t. Simple Injector will give an diagnostic error when you call Verify().
Transients are not disposed of by Simple Injector. That’s why you get a diagnostic error when you register a Transient that implements IDisposable. Again, this is very different with some other DI Containers. With MS.DI, transients are tracked and disposed of when their scope, from which they are resolved, is disposed of. There are pros and cons to this. Important con is that this will lead to accidental memory leaks when resolving disposable transients from the root container, because MS.DI will store those Transients forever.
About choosing the right lifestyle for a component:
Choosing the correct lifestyle (Transient/Scoped/Singleton) for a component is a delegate matter.
If a component contains state that should be reused throughout the whole application, you might want to register that component as Singleton -or- move the state out of the component and hide it behind a service which component can be registered as Singleton.
The expected lifetime of a component should never exceed that of its consumers. Transient is the shortest lifestyle, while Singleton is the longest. This means that a Singleton component should only depend on other Singletons, while Transient components can depend on both Transient, Scoped, and Singleton components. Scoped components should typically only have Scoped and Singleton dependencies.
The previous rule, however, is quite strict, which is why with Simple Injector v5 we decided to allow Scoped components take a dependency on Transient components as well. This will typically be fine in case scopes live for a short period of time (as is with web requests in web applications). If, however, you have long-running operations that operate within a single scope, but do regularly call back into the container to resolve new instances, having Scoped instances depend on (stateful) Transients could certainly cause trouble; that’s, however, not a very common use case.
Failing to adhere to the rule of “components should only depend on equal or longer-lived components,” results in Captive Dependencies. Simple Injector calls them “Lifestyle Mismatches,” but it’s the same thing.
A stateless component with no dependencies can be registered as Singleton.
The lifestyle of a stateless component with dependencies, depends on the lifestyle of its dependencies. If it has components that are either Scoped or Transient, it should itself be either Scoped or Transient. If it were registered as Singleton, that would lead to its dependencies becoming Captive Dependencies.
If a stateless component only has Singleton dependencies, it can be registered as Singleton as well.
When it comes to selecting the correct lifestyles for your components in the application, there are two basic Composition Models to choose from, namely the Ambient Composition Model and the Closure Composition Model. I wrote a series of five blog posts on this starting here. With the Ambient Composition Model you’ll make all components in your application stateless and store state outside of the object graphs. This allows you to register almost all your components as Singleton, but it does lead to complications and likely a somewhat different design of your application.
It's, therefore, more likely that you are applying the second Composition Model: The Closure Composition Model. This is the most common model, and used by most developers and pushed by most application frameworks (e.g. ASP.NET Core DI). With the Closure Composition Model, you would typically register most of your components as Transient. Only the few components in your application that do contain state would be registered as either Scoped or Singleton. Although you could certainly “tune” composition by looking at the consumers and dependencies of components and decide to increase the lifestyle (to Scoped or even Singleton) to prevent unneeded creation of instances, downside of this is that is more fragile.
For instance, if you have a stateless component X that depends on a Singleton component Y, you can make component X a Singleton as well. But once Y requires a Scoped or Transient dependency of its own, you will not only have to adjust the lifestyle of Y, but of X as well. This could cascade up the dependency chain. So instead, with the Closure Composition Model, it would typically be normal to keep things “transient unless.”
About performance:
Simple Injector is highly optimized, and it would typically not make much difference if a few extra components are created. Especially if they are stateless. When running a 32 bits process, such class would consume “8 + (4 * number-of-dependencies)” bytes of memory. In other words, a stateless component with 1 dependency consumes 12 bytes of memory, while a component with 5 dependencies consumes 28 bytes (assuming a 32 bits processes; multiply this by 2 under 64 bits).
On the other hand, managing and composing Scoped instances comes with its own overhead. Although Simple Injector is highly tuned in this regard, Scoped instances need to be cached and resolved from the scope’s internal dictionary. This comes at a cost. This means that creating a component with no dependencies a few times as Transient in a graph is likely faster than having it resolved as Scoped.
Under normal conditions, you wouldn’t have to worry about the amount of extra memory and the amount of extra CPU it takes to produce those extra Transient instances. But perhaps you are not under normal conditions. The following abnormal conditions could cause trouble:
If you violate the simple-injection-constructors rule: When a component’s constructor does more than simply storing its supplied dependencies (for instance calling them, doing I/O or something CPU intensive or memory intensive) creating extra transient instances can hurt a lot. You should absolutely try to stay away from this situation whenever possible.
**Your application creates massive object graphs: ** If object graphs are really big, you’ll likely see certain components being depended upon multiple (or even many) times in the graph. If the graph is massive (thousands of individual instances), this could lead to the creation of hundreds or even thousands of extra objects, especially when those components have Transient dependencies of their own. This situation often happens when components have many dependencies. If for instance your application’s components regularly have more than 5 dependencies, you’ll quickly see the size of the object graph explode. Important to note here is that this is typically caused by a violation of the Single Responsibility Principle. Components get many dependencies when they are doing too much, taking too many responsibilities. This easily causes them to have many dependencies, and when their dependencies have many dependencies, things can explode quite easily. The real solution in that case is to make your components smaller. For instance, if you have classes like “OrderService” and “CustomerService”, they will likely have a hodgepodge of functionality and a big list of dependencies. This causes a myriad of problems; big object graphs being one of them. Fixing this in an existing application, however, is typically not easy; it requires a different design and a different mindset.
In these kinds of scenarios changing a component’s lifestyle can be beneficial for the performance of the application. You already seem to have established this in your application. In general, changing the lifestyle from Transient to Scoped is a pretty safe change. This is why Simple Injector v5 doesn’t complain anymore when you inject Transient dependencies into Scoped consumers.
This will not be the case, however, when you have a stateful Transient component, while each consumer does expect to get its own state; in that case, changing it to Scope would in fact break your application. However, this is not a design that I typically endorse. Although I’ve seen this type of composition a few times in the past, I never do this in my applications; IMO it leads to unneeded complexity.
TLDR;
Long story short, there are a lot of factors to consider, and perhaps a lot of places in the application where the design could be approved, but in general (especially in the context of web requests) changing the lifestyle of stateless components from Transient to Scoped is usually pretty safe. If this results in a big performance win in your application, you can certainly consider making Scoped the default lifestyle.
From the User's Guide:
Sometimes you want to limit the number of times an #Inject-constructed
class is instantiated or a #Provides method is called, but you don’t
need to guarantee that the exact same instance is used during the
lifetime of any particular component or subcomponent.
Why would I use that instead of #Singleton?
Use #Singleton if you rely on singleton behavior and guarantees. Use #Reusable if an object would only be a #Singleton for performance reasons.
#Reusable bindings have much more in common with unscoped bindings than #Singleton bindings: You're telling Dagger that you'd be fine creating a brand-new object, but if there's a convenient object already created then Dagger may use that one. In contrast, #Singleton objects guarantee that you will always receive the same instance, which can be much more expensive to enforce.
In general, Dagger and DI prefer unscoped objects: Creating a new object is a great way to keep state tightly-contained, and allows for objects to be garbage-collected as soon as the dependent object can. Dagger shows some of this preference built-in: In Dagger unscoped objects can be mixed in to any component or module, regardless of whether the component is scope-annotated. This type of unscoped binding is also useful for stateless objects like injectable (mockable) utility classes and implementations of strategy, command, and other polymorphic behavioral design patterns: The objects should be bound globally and injected for testing/overrides, but instances don't keep any state and short-lived or disposable.
However, in Android and other performance- and memory-constrained environments, it goes against performance recommendations to create a lot of temporary objects (as described on android.com but removed since January 2022), because instance creation and garbage collection are both more-expensive processes than on desktop VMs. This leads to the pragmatic solution of marking an object #Singleton, not because it's important to always get the same instance, but just to conserve instances. This works, but is semantically-weak, and also has memory and speed implications: Your short-lived util or strategy pattern object now has to exist as long as your application exists, and must be accessed through double-checked locking, or else you risk violating the "one instance only" #Singleton guarantee that is unnecessary here. This can be a source of increased memory usage and synchronization overhead.
The compromise is in #Reusable bindings, which have instance-conserving properties like #Singleton but are excepted from the scope-matching #Component rule just like unscoped bindings—which gives you more flexibility about where you install them. (See tests.) They have a lifespan only as long as the outermost component that uses them directly, and will opportunistically use an instance from an ancestor to conserve further, but without double-checked locking to save on creation costs. (Consequently, several instances of a #Reusable object may exist simultaneously in your object graph, particularly if they were requested on multiple threads at the same time.) Finally, and most importantly, they're a signal to you and future developers about the way the class is intended to be used.
Though the cost is lower, it's not zero: As Ron Shapiro notes on Medium, "Reusable has many of the same costs as Singleton. It saves synchronization, but it still forces extra classes to be loaded at app startup. The real suggestion here is to never scope unless you’ve profiled and you’ve seen a performance improvement by scoping." You'll have to evaluate the speed and memory effects yourself: #Reusable is another useful tool in the toolbox, but that doesn't mean it's always or obviously a good choice.
In short, #Singleton would work, but #Reusable has some distinct performance advantages if the whole point is performance instead of object lifecycle. Don't forget to measure performance before and after you mark an instance #Reusable, to make sure #Reusable is really a benefit for your use case.
Follow-up question from saiedmomen: "Just to be 100% clear things like okhttpclient, retrofit and gson should be declared #Reusable. right??"
Yes, in general I think it'd be good to declare stateless utilities and libraries as #Reusable. However, if they secretly keep some state—like handling connection limits or batching across all consumers—you might want to make them #Singleton, and if they are used very infrequently from a long-lived component it might still make sense to make them scopeless so they can be garbage-collected. It's really hard to make a general statement here that works for all cases and libraries: You'll have to decide based on library functionality, memory weight, instantiation cost, and expected lifespan of the objects involved.
OkHttpClient in particular does manage its own connection and thread pools per instance, as Wyko points out in the comments, and Albert Vila Calvo likewise notes Retrofit's intended-singleton behavior. That would make those good candidates for #Singleton over #Reusable. Thanks Wyko and Albert!
We have an ASP.NET MVC app using IoC to inject Service references into controllers and Repository references into Services.
Controllers have to have a Lifetime of Transient as they must be instantiated per request. If the whole IoC stack is being newed-up per request, though, this gets to be a bit of overhead. We have more dependencies than I'd like, and one option would be to have more controllers, each with fewer dependencies in the stack. But, leaving that aside for now, my question is, if an object that is injected as a singleton has dependencies that have a transient lifetime, will those dependencies essentially be treated like singletons by virtue of being owned by the Singleton?
Specifically, if we have the following
RepositoryA (needs to be transient because current design injects a user context in constructor)
ServiceA (singleton)
ControllerA (transient)
instantiated like so:
public ServiceA(IRepositoryA repo) {}
public ControllerA(IServiceA service) {}
Will RepositoryA essentially be instantiated once because ServiceA is instantiated once?
I'm 99% sure the answer is yes, but just wanted to confirm the amount of refactoring I have to do here.
Also, assuming Services and Repositories did NOT have any user/request-specific instance variables, as a design approach, is there any reason not to use a Singleton lifetime for them?
if an object that is injected as a singleton has dependencies that
have a transient lifetime, will those dependencies essentially be
treated like singletons by virtue of being owned by the Singleton?
That's correct. Since such component holds on to its dependencies (by storing their reference in a private field), those dependencies will live as long as the component itself does. In other word, their lifetime is implicitly promoted to the lifetime of the component (if their lifetime is shorter).
If you have this, your DI configuration is most certainly wrong and sooner or later this bug will show up. Probably only in production and hardly ever on your dev machine :-S.
In general all components managed by the container should only depend on abstractions that have a lifespan that is equal or longer than that of the component itself.
Some frameworks even have analysis services in place to detect these kinds of configuration errors. Nonetheless, you should be very careful when wiring up all dependencies. In general it would be safest to configure components as transient whenever possible, since a transient components is allowed to contain dependencies of any lifestyle. Having many transient objects would normally not be a performance problem. Building a rather large object graph per web request would typically be fast enough (otherwise try switching to a DI framework with a higher throughput).
This question describes two approaches of solving the sophisticated architectural problem related to ASP.NET MVC. Unfortunately our team is quite new to this technology and we haven’t found any solid sources of information on this particular topic (except overviews where it’s said that MVC is more about separation than componentization). So as for now we are hesitating: whether our solution is appropriate or there is a different obvious way to solve this problem.
We have a requirement to make ASP.NET MVC-based design with componentization in mind. View engine Razor is also a requirement for us. The key feature here is that any level of controller’s nesting is expected (obviously thru Html.Action directive within .cshtml). Any controller could potentially obtain the data thru a webservice call (the final design can break this limitation, as it’s described below).
The issue is that the data must be obtained in async and maximum parallel fashion. E.g. if two backend calls within the controllers are independent they must be performed in parallel.
At first glance the usage of async MVC controllers could solve all the problems. But there is a hidden caveat: nested controller must be specified within cshtml only (within a view). And a .cshtml view is being parsed after the original controller finished its own async execution. So all the async operations within the nested controller will be performed in a separate async slot and therefore not in parallel with the first parent controller. This is a limitation of synchronous nature of .cshtml processing.
After a deep investigation we revealed that two options are available.
1) Have only one parent async controller which will retrieve all the data and put this data into container (dictionary or whatever). The nested controllers aren’t allowed to perform any backend calls. Instead of this they will have a reference to the initialized container with the results of all the backend calls. Bu this way the consumer of the framework must differentiate between parent and child controller which is not a brilliant solution.
2) Retrieve all the data from backends within a special async HttpModule. This module will initialize the same container which will reside, for instance within HttpContext. Obviously all the controllers in such a case will not be allowed to perform any backend calls, but they will have a unified internal structure (in comparison with #1 option).
As for now we think that the option #2 is more desirable, but we are more interested in the solid community-adopted way to solve this problem in a real enterprise-level MVC projects.
Literally any links/comments are welcomed.
[UPD] A requirement of any level of nesting of controllers came from our customer which wants a system where fully reusable MVC components will be presented. And they could be combined in any sequence with any level of nesting - as it is already done in the existing webforms-based implementation. This is a business rule for existing app that the components could be combined anyhow so we're not targeted to break this rule. As for now we think that such a component is a combination of "controller+view+metadata" where "metadata" part describes the backend calls to be performed in the scenario 1 or 2.
Why are you considering async calls here? Keep in mind if your async calls are so the asp.net threads don't get all used up since the db is taking a while to return, as soon as new requests come in they too will go to the db, thus increasing the workload and in turn gaining nothing.
To be honest though, Im having a hard time following exactly what you have in mind here. Nested controllers for...?
"The key feature here is that any level of controller’s nesting is expected"
I think I (we?) need a bit more information on that part here.
However, the warning on async still stands :)
E.g. if two backend calls within the controllers are
independent they must be performed in parallel.
If they are truly independent you might be able to use asynch JavaScript calls from the client and achieve some degree of parallelism that way.
I'm working on an API integration project in Ruby and I was about to create a class method to somewhat follow what Rails does with the finder methods but I stopped short of doing so because I'm concerned I might introduce a race condition.
I wouldn't be storing anything within the member variables, just instantiating objects with the the class method and making external API calls, so everything would be locally scoped (within the class method). Still, isn't there a potential of having a race condition as multiple threads pass through this class method? How do the Rails finder class methods avoid this? Or am I not understanding something at a more fundamental level here?
It's possible you're not understanding how threads work, or that you're not describing some part of your problem that would be the source of a race condition.
Merely calling a method in two different threads isn't sufficient to cause a race condition. Unless there's some shared resource that might be in an inconsistent state because another thread is in the middle of using it, a race condition isn't really a problem.
If all of your variables are scoped to the method, then the only source of a race that I can glean from your description of the problem might be the API calls. If it's possible that while one thread is in the middle of accessing the API, another comes through and restarts whatever interaction was going on, and that would be problematic, then you might have a race problem.