• G
    [release/8.0] [DependencyInjection] introduce feature switch to disable S.R.E (#91352) · 399f37c6
    github-actions[bot] 提交于
    * [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.
    
    * Update docs/workflow/trimming/feature-switches.md
    Co-authored-by: NEric Erhardt <eric.erhardt@microsoft.com>
    
    ---------
    Co-authored-by: NJonathan Peppers <jonathan.peppers@microsoft.com>
    Co-authored-by: NJonathan Peppers <jonathan.peppers@gmail.com>
    Co-authored-by: NEric Erhardt <eric.erhardt@microsoft.com>
    399f37c6
ILLink.Substitutions.xml 688 字节