From 887a3a9f807a72d0ce3d20a5805547a4ef8c37a8 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 22 Jun 2021 08:30:13 -0700 Subject: [PATCH] Improve performance of IsRootScope check - Stash a field instead of doing an equality comparison. Fixes #54351 --- .../src/ServiceLookup/ServiceProviderEngineScope.cs | 5 +++-- .../src/ServiceProvider.cs | 4 ++-- .../tests/DI.Tests/ServiceProviderEngineScopeTests.cs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs index 06498ff98baac..4ad8b1579a029 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs @@ -16,10 +16,11 @@ internal sealed class ServiceProviderEngineScope : IServiceScope, IServiceProvid private bool _disposed; private List _disposables; - public ServiceProviderEngineScope(ServiceProvider provider) + public ServiceProviderEngineScope(ServiceProvider provider, bool isRootScope) { ResolvedServices = new Dictionary(); RootProvider = provider; + IsRootScope = isRootScope; } internal Dictionary ResolvedServices { get; } @@ -29,7 +30,7 @@ public ServiceProviderEngineScope(ServiceProvider provider) // For other scopes, it protects ResolvedServices and the list of disposables internal object Sync => ResolvedServices; - public bool IsRootScope => this == RootProvider.Root; + public bool IsRootScope { get; } internal ServiceProvider RootProvider { get; } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index d21d9807f5f77..fb7052ec8ea66 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -36,7 +36,7 @@ internal ServiceProvider(IEnumerable serviceDescriptors, Serv _createServiceAccessor = CreateServiceAccessor; _realizedServices = new ConcurrentDictionary>(); - Root = new ServiceProviderEngineScope(this); + Root = new ServiceProviderEngineScope(this, isRootScope: true); CallSiteFactory = new CallSiteFactory(serviceDescriptors); // The list of built in services that aren't part of the list of service descriptors // keep this in sync with CallSiteFactory.IsService @@ -173,7 +173,7 @@ internal IServiceScope CreateScope() ThrowHelper.ThrowObjectDisposedException(); } - return new ServiceProviderEngineScope(this); + return new ServiceProviderEngineScope(this, isRootScope: false); } private ServiceProviderEngine GetEngine() diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs index 5c19caa922e76..d43752db21eba 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs @@ -12,7 +12,7 @@ public class ServiceProviderEngineScopeTests public void DoubleDisposeWorks() { var provider = new ServiceProvider(new ServiceCollection(), ServiceProviderOptions.Default); - var serviceProviderEngineScope = new ServiceProviderEngineScope(provider); + var serviceProviderEngineScope = new ServiceProviderEngineScope(provider, isRootScope: true); serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(typeof(IFakeService), 0), null); serviceProviderEngineScope.Dispose(); serviceProviderEngineScope.Dispose();