From 5c4a4993d5d62634b570650be58e2c3aaf70a779 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 14 Jun 2022 15:30:51 -0500 Subject: [PATCH] [core] use Lazy for MauiContext properties Context: https://github.com/unoplatform/performance/tree/master/src/dopes/DopeTestMaui Building upon #7996 and #8001, I noticed while profiling the sample app putting N `Label` on the screen: 405.02ms (2.3%) microsoft.maui!Microsoft.Maui.MauiContext.get_Context() 77.90ms (0.44%) microsoft.maui!Microsoft.Maui.MauiContext.get_Handlers() Meaning that around ~2.74% of the time was spent just calling these two properties. These properties hit Microsoft.Extensions each time to locate the service: public Android.Content.Context? Context => _services.GetService(); These are core-services that wouldn't change after startup, so should we just use `Lazy` instead of doing a call like this each time? I also made use of `ANDROID`, as that is the preferred define to use in .NET 6+ instead of `__ANDROID__`: https://github.com/dotnet/designs/blob/a447d77bb53d189746ccd80c2d814064c2b6c606/accepted/2020/net5/net5.md#vary-implementation ~~ Results ~~ A `Release` build on a Pixel 5 device, I was getting: Before: 81.70 Dopes/s After: 91.94 Dopes/s --- src/Core/src/MauiContext.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Core/src/MauiContext.cs b/src/Core/src/MauiContext.cs index 6d6dfbc1256d..341f0a423205 100644 --- a/src/Core/src/MauiContext.cs +++ b/src/Core/src/MauiContext.cs @@ -7,8 +7,13 @@ namespace Microsoft.Maui public class MauiContext : IMauiContext { readonly WrappedServiceProvider _services; + readonly Lazy _handlers; + +#if ANDROID + readonly Lazy _context; + + public Android.Content.Context? Context => _context.Value; -#if __ANDROID__ public MauiContext(IServiceProvider services, Android.Content.Context context) : this(services) { @@ -19,17 +24,15 @@ public MauiContext(IServiceProvider services, Android.Content.Context context) public MauiContext(IServiceProvider services) { _services = new WrappedServiceProvider(services ?? throw new ArgumentNullException(nameof(services))); + _handlers = new Lazy(() => _services.GetRequiredService()); +#if ANDROID + _context = new Lazy(() => _services.GetService()); +#endif } public IServiceProvider Services => _services; - public IMauiHandlersFactory Handlers => - Services.GetRequiredService(); - -#if __ANDROID__ - public Android.Content.Context? Context => - Services.GetService(); -#endif + public IMauiHandlersFactory Handlers => _handlers.Value; internal void AddSpecific(TService instance) where TService : class