Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/8.0] [DependencyInjection] introduce feature switch to disable S.R.E #91352

Merged
merged 2 commits into from
Aug 31, 2023

Commits on Aug 30, 2023

  1. [DependencyInjection] introduce feature switch to disable S.R.E

    When recording a new AOT profile for .NET MAUI apps running on Android,
    we noticed that System.Reflection.Emit work was being done on a
    background thread. The call seen in `dotnet-trace` output:
    
        11.32ms microsoft.extensions.dependencyinjection!Microsoft.Extensions.DependencyInjection.ServiceLookup.ILEmitResolverBuilder.GenerateMethodBody(Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite,System.Reflection.Emit.ILGenerator)
    
    .NET Android apps are unique in that there is a JIT,
    `RuntimeFeature.IsDynamicCodeCompiled` is true, System.Reflection.Emit
    is possible -- S.R.E is however, not great for startup performance.
    
    Starting threads on Android during startup can also be slow, as Android
    will commonly put all but a single core to sleep for battery saving
    purposes. We try to avoid starting threads on startup for "hello world"
    applications on Android.
    
    To solve this for now, introduce a new feature flag:
    
        Microsoft.Extensions.DependencyInjection.DisableDynamicEngine
    
    Which, we will provide a value in either the Android or .NET MAUI
    optional workload via an MSBuild property. To test, I put this in my
    app's `.csproj` file:
    
        <RuntimeHostConfigurationOption Include="Microsoft.Extensions.DependencyInjection.DisableDynamicEngine"
                                        Condition="'$(DisableDynamicEngine)' != ''"
                                        Value="$(DisableDynamicEngine)"
                                        Trim="true" />
    
    Customers *could* opt to change this flag, but we don't think it will
    particularly useful. An example of services realized by .NET MAUI at
    startup, via some logging added:
    
        08-25 13:21:55.647 16530 16530 I DOTNET  : RealizeService called: System.Collections.Generic.IEnumerable`1[Microsoft.Maui.Hosting.IMauiInitializeService]
        08-25 13:21:55.664 16530 16530 I DOTNET  : RealizeService called: System.Collections.Generic.IEnumerable`1[Microsoft.Maui.Hosting.IMauiInitializeScopedService]
        08-25 13:21:55.665 16530 16530 I DOTNET  : RealizeService called: Microsoft.Maui.Dispatching.IDispatcher
        08-25 13:21:55.668 16530 16530 I DOTNET  : RealizeService called: System.Collections.Generic.IEnumerable`1[Microsoft.Maui.LifecycleEvents.LifecycleEventRegistration]
        08-25 13:21:56.057 16530 16530 I DOTNET  : RealizeService called: System.Collections.Generic.IEnumerable`1[Microsoft.Maui.Hosting.HandlerMauiAppBuilderExtensions+HandlerRegistration]
        08-25 13:21:56.115 16530 16530 I DOTNET  : RealizeService called: Microsoft.Extensions.DependencyInjection.IServiceScopeFactory
        08-25 13:21:56.670 16530 16530 I DOTNET  : RealizeService called: Microsoft.Maui.Controls.HideSoftInputOnTappedChangedManager
        08-25 13:21:56.712 16530 16530 I DOTNET  : RealizeService called: System.Collections.Generic.IEnumerable`1[Microsoft.Maui.Hosting.ImageSourcesMauiAppBuilderExtensions+ImageSourceRegistration]
        08-25 13:21:57.700 16530 16530 I DOTNET  : RealizeService using S.R.E: Microsoft.Maui.Controls.HideSoftInputOnTappedChangedManager
    
    `HideSoftInputOnTappedChangedManager` would be realized once per page,
    which would not be a huge payoff to use S.R.E for. So the only way the
    S.R.E codepath could be useful on Android would be if the customer is
    registering lots of services themselves. They might be better off just
    using `new()` in that case?
    
    An example of the startup time Android reports with the new flag on/off:
    
        DisableDynamicEngine=false
        08-25 14:31:37.462  2090  2330 I ActivityTaskManager: Displayed com.companyname.testmaui/crc643c09abdeec717b83.MainActivity: +733ms
        08-25 14:31:39.394  2090  2330 I ActivityTaskManager: Displayed com.companyname.testmaui/crc643c09abdeec717b83.MainActivity: +737ms
        08-25 14:31:41.326  2090  2330 I ActivityTaskManager: Displayed com.companyname.testmaui/crc643c09abdeec717b83.MainActivity: +730ms
        DisableDynamicEngine=true
        08-25 14:32:20.233  2090  2330 I ActivityTaskManager: Displayed com.companyname.testmaui/crc643c09abdeec717b83.MainActivity: +724ms
        08-25 14:32:22.137  2090  2330 I ActivityTaskManager: Displayed com.companyname.testmaui/crc643c09abdeec717b83.MainActivity: +727ms
        08-25 14:32:24.042  2090  2330 I ActivityTaskManager: Displayed com.companyname.testmaui/crc643c09abdeec717b83.MainActivity: +716ms
    
    This was a `dotnet new maui` project, using dotnet/maui/main on a Pixel
    5 device.
    jonathanpeppers authored and github-actions committed Aug 30, 2023
    Configuration menu
    Copy the full SHA
    cb95864 View commit details
    Browse the repository at this point in the history
  2. Update docs/workflow/trimming/feature-switches.md

    Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>
    2 people authored and github-actions committed Aug 30, 2023
    Configuration menu
    Copy the full SHA
    ca883f7 View commit details
    Browse the repository at this point in the history