I would like to understand the memory and performance implications of singleton vs injected services in Angular 7.
For example, let's say that I have a list of components on a page and each one is injected the same service (i.e. it's listed in the component providers). Does this mean that if I have e.g. 50 components, I will need 50 times the memory requirements for the injected service, vs a singleton service that is common to all?
Are there any other performance implications to consider?
I would like to understand the memory and performance implications of singleton vs injected services in Angular 7.
Dependencies in Angular are handled via providers. There are many types of providers such as constant values, factories, classes etc.. etc..
A service refers to an injectable class that has been instantiated. When it is instantiated depends upon when it is provided. The most common place to declare a provider is in the declaration of a module. So we refer to this as the scope of the provider.
A provider by default is a single value resolver, but it's possible to configure a provider as multiple. For simplicity sacks let's assume providers are singletons within a scope.
A scope can have a parent and children. When a provider is declared it is provided in the current scope. Modules tend to be very high up on the injector tree with the root at the top.
When a component is created we can think of that as a new scope. With the bootstrap component at the top of the component tree, but given that you can use a factory to create a new component means you shouldn't assume everything is part of the same tree.
Yeah it can get complicated.
For example, let's say that I have a list of components on a page and each one is injected the same service (i.e. it's listed in the component providers).
Let's assume this service is named FooBarService
. I can explain the many different things that can happen based upon how you've configured the dependency injector.
FooBarService
is an unknown dependency.FooBarService
and this component and all other components will receive the same instance.FooBarService
and this component will receive an instance, but components outside the lazy module will throw an error of unknown dependency.FooBarService
and all its children components will receive an instance.FooBarService
and each component receives a new instance.Since you've stated "it's listed in the component providers" then option #5 would apply.
See this reference: https://angular.io/guide/providers#providing-services-in-modules-vs-components
Does this mean that if I have e.g. 50 components, I will need 50 times the memory requirements for the injected service, vs a singleton service that is common to all?
Yes, if you have declared the provider in the scope of a component and not the scope of a module. There will be one instance per component that has declared it, but that instanced is shared for the children of that component.
Are there any other performance implications to consider?
Yes, it requires more memory and time to create 50 components if the injector has to create new instances. Will it have a negative impact on your software? As with any decision it depends upon why you are doing it. If it is to resolve a dependency problem, then it might be the only way to do it. If you can use a shared singleton service instead, then I would wonder why you weren't doing that.
Does this mean that if I have e.g. 50 components, I will need 50 times the memory requirements for the injected service, vs a singleton service that is common to all?
This will only happen if each component has a different module and:
each module provide the service;
or the service is provided in one module and this module is imported in each component module;
If any component share a module whose provide the service, it will be singleton around these components.
I've reading a very good article from Netanel Basal - "Angular Services do NOT have to be Singleton"
Where he says about singleton services:
The sole purpose of the service is to share data between child’s components and to provide a couple of helper’s methods.
If you have a singleton service, it will be only one instance but in the whole application lifecycle (even when you are not using it), otherwise, if you have non singleton services instances, it will be consuming much more memory and each service intance will be destroyed only when all component of its module was destroyed.
I would say that you could try to control the trade-off of these benefits in your application.
Other non singleton benefit is:
We can even implement ngOnInit
and ngOnDestroy
lifecycle, you can check it here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With