IoC Container Performance

Most Xamarin.Forms applications, will use Dependency Injection, and hence an IoC (Inversion of Control) container. In this post, we will be looking at the performance of these frameworks, in 3 scenarios.

  1. Registering types into the container
  2. Resolving a simple type
  3. Resolving a type, with dependency injection, through the constructor.

Types

These are the types and interfaces I created. Second is a simple type, with no dependencies. Example, requires Second as a parameter in the constructor.

public interface ISecond { }
public class Second : ISecond { }
public interface IExample { }
public class Example : IExample
{
    public Example(ISecond second) { }
}

As a point of interest, each framework only constructed each object as required. No object was created when it was registered.

Environment and Testing

These tests were run on an Android simulator, on my i7-7700HQ. No AOT or anything other than default settings were used. iOS is much faster, as is AOT with Android. I chose Android in this setup, because it would be the slowest configuration. As a rough guide, testing showed iOS as 4-5x faster.

Here is an example, of how I tested.

Test 1

Stopwatch s = new Stopwatch();
s.Start();
Locator.CurrentMutable.RegisterLazySingleton(() => new Second(), typeof(ISecond));
Locator.CurrentMutable.RegisterLazySingleton(() => new Example(Locator.Current.GetService<ISecond>()), typeof(IExample));
s.Stop();

Test 2

Stopwatch s = new Stopwatch();
s.Start();
Locator.Current.GetService<ISecond>();
s.Stop();

Test 3

Stopwatch s = new Stopwatch();
s.Start();
Locator.Current.GetService<IExample>();
s.Stop();

Similar code was used for each other framework.

Results

Registering: Create the container and register both types.

Resolve: Retrieving an instance of the Second type.

Resolve with CI: Retrieving an instance of the Example type, that requires the Second type as constructor parameter.

These times are specific to each task. E.g. Resolving, does not include the time of registering. Add the values together if you want to see the cumulative time registering and resolving.

FrameworkRegister TypeResolveResolve with CI
AutoFac (4.6.1)212ms284ms332ms
Caliburn.Micro (3.2.0)20ms134ms140ms
DryIoc (2.12.3)138ms276ms294ms
FreshMVVM (2.2.0)18ms128ms131ms
MVVMCross (5.3.0)5ms118ms123ms
MVVMLight (5.3.0)16ms118ms128ms
Splat (2.0.0)22ms105ms111ms
Unity (5.0-rc1)76ms515ms593ms
Xamarin.Forms (2.4.0)1ms99msN/A

* Xamarin.Forms does not support Constructor Injection, hence while it’s the fastest, it doesn’t have nearly as many capabilities as other frameworks.

What about ReactiveUI, Exrin, or Prism? ReactiveUI uses Splat, and the other MVVM frameworks allow you to choose your own IoC framework, hence Splat, DryIoC, AutoFac or Unity can be used.

Summary

Most of the Xamarin.Forms MVVM Frameworks offer very similar performance in registering types, and resolving instances. Dedicated IoC frameworks tend to have the worst performance, with Unity, DryIoC and AutoFac offering the worse performance. If you are using Exrin or Prism, it may be worthwhile to use Splat or a TinyIoC variant.

Dedicated IoC frameworks, offer many more features, and capabilities, however it is unlikely you will use them. As such, keeping it simple, will keep your Xamarin.Forms app faster, with no loss of functionality in most Xamarin.Forms apps.


XAMARIN.FORMS MONTHLY NEWSLETTER

JOIN 1,100+ SUBSCRIBERS

  1. Don't miss out on updates
  2. The latest info from this site, Xamarin and the community
  3. Unsubscribe at any time*

* We use MailChimp, with double opt-in, and instant unsubscribe

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer | Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

16 Comments

  1. Riza Marhaban

    Hi Adam, nicely explained. Been looking this perf benchmark for awhile. With this perf you have tested, can we say Xamarin.Forms vanilla would be the best choice for Xamarin Form apps development, or at least choose the fastest IoC framework? Which one you suggest and preferably choose.

    1. Adam Pedley

      Vanilla XF doesn’t support Constructor Injection, hence I would recommend using Splat, or the MVVM framework default, if they come with one. I am a firm believer that constructor injection is the best way for IoC, and unfortunately XF doesn’t support that. 🙁

  2. Glenn Watson

    Not much actual detail of your testing methods here. Not even mention if this is one object you are resolving, 100,000 etc. Also although I’ve added Expression tree support to Splat through a overload by default it doesn’t support automatic constructor injection also, but by the nature of it using func’s you can just resolve the other dependencies at the same time.

    1. Adam Pedley

      It’s only one object I am resolving. I thought about doing 100,000, but there is no point. I don’t know of any Xamarin.Forms app that needs 100,000 types resolved all at once. Those types of tests I believe are better suited to web based technology, where high requests can actually cause that type of load.

      The tests were also rather simple. Construct the container and register the 2 types. Then resolve one type, then resolve one type, that requires a second type to be injected in the constructor.

  3. Andrei

    I’m using Xamarin Forms + Prism.Forms + Prism.Unity.
    I’ve always been suspicious about the time it takes to inject the services in the view-models.
    Based on your tests, 500ms for resolving just one object is horrific.

    On the other hand the idea of switching to Autofac and Dryloc is not appealing to me. I wonder if Unity has issues on Xamarin or it’s slow on Windows too.

    1. Adam Pedley

      It will be quicker on Windows and iOS. It will be quicker on Android with AOT enabled as well. However it will still always be the worse performing. I believe Prism has a DryIoC plugin, that might make it easy for you to switch over. And while it’s not the best, it’s much better than Unity.

  4. Tommy Baggett

    Once again Adam, you’re providing great guidance for Xamarin.Forms development. I’ve also been using Prism and Unity, but will now switch to DryIoC and measure the difference in app startup, workflow performance, etc.

    Thanks as always for sharing your findings with the community!

    1. Vinod

      Hey Tommy,

      I am on the same boat as you are. Having a lot of issues with Unity (with ContainerControlledLifeTimeManager). Thinking of changing to anything but Unity for PrismForms. Just curious, how you went with your switch over. Please do share your experience.

      – Vinod

  5. Rasmus Tolstrup Christensen

    Really good article, great to see som numbers. I’ve been using Unity as it was just easy to get going. Is there any difference if you make this test on a debug og release build? I will consider switching to dryioc and give it a try. After all, with XF forms I mostly use it as registration and constructor resolving.

    1. Adam Pedley

      Oops, I should not perform these tests when I’m still recovering from the flu. These were actually done in debug mode, but in Release mode, they show a 20%-30% reduction in time, so still not too much. Unity still has a 420ms initial resolve time, with CI. Ratio’s all hold. I will go and update this post soon.

  6. Yves Delcoigne

    Thanks for the great article, Adam! After reading this, I’m inclined to switch from AutoFac to Splat, but I’m also curious as to how SimpleInjector performs compared to these containers. Do you have any advice on that?

  7. Max

    Can we get a link to a repro repo, on GitHub or something?

    I’m curious because you mention:
    No object was created when it was registered.

    But then have object creation in the register:
    Locator.CurrentMutable.RegisterLazySingleton(() => new Second(), typeof(ISecond));
    Locator.CurrentMutable.RegisterLazySingleton(() => new Example(Locator.Current.GetService()), typeof(IExample));

    I think it would be of interest to see how the other frameworks were registered and used.

    Cheers!

    1. Adam Pedley

      You’ll notice it is passing through a Func, hence it’s not actually calling that code, until a get is actually called.

      Most other frameworks have registrations similar to container.Register<I, T>().

      Either way, it is still correct that nothing is instantiated upon registration, only upon the first get, by the framework itself.