Azure / Azure/azure-functions-host

Performance Area: Dependency Injection

Open
#8,073 0 comments 0 reactions 1 assignee Claimed by @brettsam View on GitHub
area: dependency injection perf perf: cold-start
Dominant language
C#
Stars
2k
Forks
482
Avg merge
2d 10h
Merged PRs (30d)
36

Description

In profiling the v4 runtime, we detected a regression that went unnoticed because paired with the .NET 6.0 gains it was about even. [In the ScopedResolver](https://github.com/Azure/azure-functions-host/blob/2fecc8b752ca60d0ef22b7c502c034a90e11a1b1/src/WebJobs.Script.WebHost/DependencyInjection/ScopedResolver.cs#L60), we are doing this:

```cs
scopedContext.UseInstance(scope.ServiceProvider);
```

In DryIoc, the ultimate behavior here is to correctly resolve transient services (PR #6721, solving #5098), but the way in which it does that is copying the immutable tree of service references.

In the below analysis, **these are for 5,000 requests to hello world** to give an order of magnitude. This is what the top allocations look like with this in play:
DryIoc Allocations

If we experiment with only commenting out that line of code (but re-introducing the original transient problem in #5098), it looks like this:

Without DryIoc allocations

Here's the allocation subtrees of `ScopedResolve.CreateChildScope()` with it in play (it's in a few spots due to lambdas):
```
Totally allocated in sub-tree of : Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.CreateScope()
Objects : 357478
Bytes : 16949208

6.56% CreateScope • 16.16 MB / - • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.CreateScope()
6.56% CreateChildScope • 16.16 MB / 1.24 MB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver.CreateChildScope(IServiceScopeFactory)
new System.Threading.Tasks.ContinuationResultTaskFromTask • 334.1 KB
new System.Func • 267.9 KB
new System.Func • 267.3 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0 • 234.4 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ServiceScope • 167.5 KB
3.97% UseInstance • 9.79 MB / 602.9 KB • DryIoc.Container.UseInstance(Type, Object, IfAlreadyRegistered, Boolean, Boolean, Object)
new DryIoc.Container+<>c__DisplayClass26_0 • 334.9 KB
new System.Func • 267.9 KB
3.74% Swap • 9.20 MB / 9.2 KB • ImTools.Ref.Swap(T, Func)
new System.SByte[] • 8.0 KB
new System.InvalidOperationException • 1.3 KB
3.73% b__0 • 9.19 MB / 356.7 KB • DryIoc.Container+<>c__DisplayClass26_0.b__0(Container+Registry)
new DryIoc.Container+<>c__DisplayClass26_1 • 356.7 KB
1.91% AddOrUpdate • 4.70 MB / - • ImTools.ImHashMap.AddOrUpdate(K, V)
1.91% AddOrUpdate • 4.70 MB / 535.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 535.0 KB
1.70% AddOrUpdate • 4.18 MB / 535.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 535.0 KB
1.49% AddOrUpdate • 3.66 MB / 535.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 535.0 KB
1.27% AddOrUpdate • 3.13 MB / 535.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 535.0 KB
1.06% AddOrUpdate • 2.61 MB / 535.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 535.0 KB
0.85% AddOrUpdate • 2.09 MB / 535.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 535.0 KB
0.64% AddOrUpdate • 1.57 MB / 535.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 535.0 KB
0.42% AddOrUpdate • 1.04 MB / 1.04 MB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 535.0 KB
new ImTools.ImHashMap+Data • 535.0 KB
1.19% SetOrAdd • 2.92 MB / - • DryIoc.Scope.SetOrAdd(Int32, Object)
0.97% TrackDisposable • 2.40 MB / 356.7 KB • DryIoc.Scope.TrackDisposable(IDisposable, Int32)
new DryIoc.Scope+<>c__DisplayClass19_0 • 356.7 KB
0.78% AddOrUpdateImpl • 1.92 MB / 577.3 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 577.3 KB
0.49% AddOrUpdateImpl • 1.21 MB / 355.1 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 355.1 KB
0.31% AddOrUpdateImpl • 772.8 KB / 308.9 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 308.9 KB
0.16% AddOrUpdateImpl • 399.6 KB / 226.9 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 226.9 KB
0.06% AddOrUpdateImpl • 155.4 KB / 123.2 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 123.2 KB
0.01% AddOrUpdateImpl • 32.2 KB / 32.2 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 32.2 KB
<0.01% KeepBalance • 17.3 KB / 17.3 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 17.3 KB
0.03% KeepBalance • 64.3 KB / 64.3 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 64.3 KB
0.05% KeepBalance • 114.6 KB / 114.6 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 114.6 KB
0.06% KeepBalance • 143.0 KB / 143.0 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 143.0 KB
0.05% KeepBalance • 137.2 KB / 137.2 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 137.2 KB
0.21% AddOrUpdateImpl • 535.0 KB / 535.0 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 535.0 KB
0.50% WithServices • 1.22 MB / 1.22 MB • DryIoc.Container+Registry.WithServices(ImHashMap)
new DryIoc.Container+Registry • 713.4 KB
new ImTools.Ref>>> • 267.5 KB
new ImTools.Ref> • 267.5 KB
0.41% CreateScope • 1.01 MB / 201.0 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.WebHostServiceProvider.CreateScope()
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceScope • 100.5 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider • 100.5 KB
0.19% OpenScope • 468.9 KB / 468.9 KB • DryIoc.ResolverContext.OpenScope(IResolverContext, Object, Boolean, Boolean)
new DryIoc.Scope • 267.9 KB
new System.Object • 100.5 KB
new DryIoc.ResolverContext+<>c__DisplayClass11_0 • 100.5 KB
0.15% WithCurrentScope • 368.4 KB / 368.4 KB • DryIoc.Container.WithCurrentScope(IScope, Boolean)
new DryIoc.Container • 368.4 KB
0.37% With • 937.8 KB / 468.9 KB • DryIoc.Container.With(Rules, IScopeContext, RegistrySharing, IScope)
new DryIoc.Container • 368.4 KB
new ImTools.Ref • 100.5 KB
0.19% WithoutCache • 468.9 KB / 468.9 KB • DryIoc.Container+Registry.WithoutCache()
new DryIoc.Container+Registry • 267.9 KB
new ImTools.Ref> • 100.5 KB
new ImTools.Ref>>> • 100.5 KB
0.20% .ctor • 502.4 KB / 502.4 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ServiceScope..ctor(IResolverContext, IServiceScope)
new System.Threading.Tasks.Task • 301.4 KB
new System.Threading.Tasks.TaskCompletionSource • 100.5 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider • 100.5 KB
0.19% OpenScope • 468.9 KB / 468.9 KB • DryIoc.ResolverContext.OpenScope(IResolverContext, Object, Boolean, Boolean)
new DryIoc.Scope • 267.9 KB
new DryIoc.ResolverContext+<>c__DisplayClass11_0 • 100.5 KB
new System.Object • 100.5 KB
0.19% WithoutUnknownServiceResolver • 468.9 KB / 368.4 KB • DryIoc.Rules.WithoutUnknownServiceResolver(Rules+UnknownServiceResolver)
new DryIoc.Rules • 368.4 KB
0.04% RemoveAt • 100.5 KB / 100.5 KB • ImTools.ArrayTools.RemoveAt(T[], Int32)
new DryIoc.Rules+UnknownServiceResolver[] • 100.5 KB
0.16% b__0 • 401.9 KB / 401.9 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0.b__0(Rules)
new DryIoc.Rules+UnknownServiceResolver • 267.9 KB
new DryIoc.Rules+UnknownServiceResolver[] • 134.0 KB
0.15% WithCurrentScope • 368.4 KB / 368.4 KB • DryIoc.Container.WithCurrentScope(IScope, Boolean)
new DryIoc.Container • 368.4 KB
0.15% WithUnknownServiceResolvers • 368.4 KB / 368.4 KB • DryIoc.Rules.WithUnknownServiceResolvers(Rules+UnknownServiceResolver[])
new DryIoc.Rules • 368.4 KB
0.13% EnsureContingentPropertiesInitializedUnsafe • 334.1 KB / 334.1 KB • System.Threading.Tasks.Task.EnsureContingentPropertiesInitializedUnsafe()
new System.Threading.Tasks.Task+ContingentProperties • 334.1 KB
0.08% TryAddInternal • 200.5 KB / 200.5 KB • System.Collections.Concurrent.ConcurrentDictionary.TryAddInternal(TKey, Nullable, TValue, Boolean, Boolean, TValue)
new System.Collections.Concurrent.ConcurrentDictionary+Node • 200.5 KB
0.07% ContinueWithCore • 167.1 KB / 167.1 KB • System.Threading.Tasks.Task.ContinueWithCore(Task, TaskScheduler, CancellationToken, TaskContinuationOptions)
new System.Threading.Tasks.ContinueWithTaskContinuation • 167.1 KB
```
```
Totally allocated in sub-tree of : DryIoc.Container.ResolveFactory(Request)
Objects : 25722
Bytes : 1337544

0.52% ResolveFactory • 1.28 MB / - • DryIoc.Container.ResolveFactory(Request)
0.32% b__2 • 803.8 KB / 636.4 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0.b__2(Request)
new DryIoc.FactoryDelegate • 267.9 KB
new DryIoc.DelegateFactory • 234.4 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_1 • 134.0 KB
0.07% WithAsResolutionCall • 167.5 KB / - • DryIoc.Setup.WithAsResolutionCall()
0.07% MemberwiseClone • 167.5 KB / 167.5 KB • System.Object.MemberwiseClone()
new DryIoc.Setup+ServiceSetup • 167.5 KB
```
```
Totally allocated in sub-tree of : DryIoc.Container.ResolveFactory(Request)
Objects : 3330
Bytes : 173160

0.07% ResolveFactory • 169.1 KB / - • DryIoc.Container.ResolveFactory(Request)
0.04% b__2 • 104.1 KB / 82.4 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0.b__2(Request)
new DryIoc.FactoryDelegate • 34.7 KB
new DryIoc.DelegateFactory • 30.4 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_1 • 17.3 KB
<0.01% WithAsResolutionCall • 21.7 KB / - • DryIoc.Setup.WithAsResolutionCall()
<0.01% MemberwiseClone • 21.7 KB / 21.7 KB • System.Object.MemberwiseClone()
new DryIoc.Setup+ServiceSetup • 21.7 KB
```
```
Totally allocated in sub-tree of : Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass5_1.b__2(HttpContext)
Objects : 383966
Bytes : 18137064

7.02% b__2 • 17.30 MB / - • Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass5_1.b__2(HttpContext)
7.02% get_RequestServices • 17.30 MB / - • Microsoft.AspNetCore.Http.Features.RequestServicesFeature.get_RequestServices()
7.02% CreateScope • 17.30 MB / - • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.CreateScope()
7.02% CreateChildScope • 17.30 MB / 1.24 MB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver.CreateChildScope(IServiceScopeFactory)
new System.Threading.Tasks.ContinuationResultTaskFromTask • 334.9 KB
new System.Func • 268.4 KB
new System.Func • 267.9 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0 • 234.9 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ServiceScope • 167.8 KB
4.43% UseInstance • 10.91 MB / 604.0 KB • DryIoc.Container.UseInstance(Type, Object, IfAlreadyRegistered, Boolean, Boolean, Object)
new DryIoc.Container+<>c__DisplayClass26_0 • 335.5 KB
new System.Func • 268.4 KB
4.19% Swap • 10.32 MB / 7.4 KB • ImTools.Ref.Swap(T, Func)
new System.SByte[] • 6.4 KB
new System.InvalidOperationException • 1.0 KB
4.19% b__0 • 10.31 MB / 397.3 KB • DryIoc.Container+<>c__DisplayClass26_0.b__0(Container+Registry)
new DryIoc.Container+<>c__DisplayClass26_1 • 397.3 KB
2.13% AddOrUpdate • 5.24 MB / - • ImTools.ImHashMap.AddOrUpdate(K, V)
2.13% AddOrUpdate • 5.24 MB / 596.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 596.0 KB
1.89% AddOrUpdate • 4.66 MB / 596.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 596.0 KB
1.65% AddOrUpdate • 4.07 MB / 596.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 596.0 KB
1.42% AddOrUpdate • 3.49 MB / 596.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 596.0 KB
1.18% AddOrUpdate • 2.91 MB / 596.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 596.0 KB
0.95% AddOrUpdate • 2.33 MB / 596.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 596.0 KB
0.71% AddOrUpdate • 1.75 MB / 596.0 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 596.0 KB
0.47% AddOrUpdate • 1.16 MB / 1.16 MB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 596.0 KB
new ImTools.ImHashMap+Data • 596.0 KB
1.35% SetOrAdd • 3.33 MB / - • DryIoc.Scope.SetOrAdd(Int32, Object)
1.11% TrackDisposable • 2.75 MB / 397.3 KB • DryIoc.Scope.TrackDisposable(IDisposable, Int32)
new DryIoc.Scope+<>c__DisplayClass19_0 • 397.3 KB
0.89% AddOrUpdateImpl • 2.19 MB / 648.5 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 648.5 KB
0.57% AddOrUpdateImpl • 1.40 MB / 419.3 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 419.3 KB
0.35% AddOrUpdateImpl • 874.9 KB / 361.1 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 361.1 KB
0.18% AddOrUpdateImpl • 445.5 KB / 264.2 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 264.2 KB
0.06% AddOrUpdateImpl • 163.9 KB / 130.7 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 130.7 KB
0.01% AddOrUpdateImpl • 33.2 KB / 33.2 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 33.2 KB
<0.01% KeepBalance • 17.4 KB / 17.4 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 17.4 KB
0.03% KeepBalance • 68.3 KB / 68.3 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 68.3 KB
0.05% KeepBalance • 134.4 KB / 134.4 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 134.4 KB
0.07% KeepBalance • 168.8 KB / 168.8 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 168.8 KB
0.07% KeepBalance • 168.4 KB / 168.4 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 168.4 KB
0.24% AddOrUpdateImpl • 596.0 KB / 596.0 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 596.0 KB
0.55% WithServices • 1.36 MB / 1.36 MB • DryIoc.Container+Registry.WithServices(ImHashMap)
new DryIoc.Container+Registry • 794.7 KB
new ImTools.Ref>>> • 298.0 KB
new ImTools.Ref> • 298.0 KB
0.41% CreateScope • 1.02 MB / 201.3 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.WebHostServiceProvider.CreateScope()
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceScope • 100.7 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider • 100.7 KB
0.19% OpenScope • 469.8 KB / 469.8 KB • DryIoc.ResolverContext.OpenScope(IResolverContext, Object, Boolean, Boolean)
new DryIoc.Scope • 268.4 KB
new DryIoc.ResolverContext+<>c__DisplayClass11_0 • 100.7 KB
new System.Object • 100.7 KB
0.15% WithCurrentScope • 369.1 KB / 369.1 KB • DryIoc.Container.WithCurrentScope(IScope, Boolean)
new DryIoc.Container • 369.1 KB
0.37% With • 939.5 KB / 469.8 KB • DryIoc.Container.With(Rules, IScopeContext, RegistrySharing, IScope)
new DryIoc.Container • 369.1 KB
new ImTools.Ref • 100.7 KB
0.19% WithoutCache • 469.8 KB / 469.8 KB • DryIoc.Container+Registry.WithoutCache()
new DryIoc.Container+Registry • 268.4 KB
new ImTools.Ref> • 100.7 KB
new ImTools.Ref>>> • 100.7 KB
0.20% .ctor • 503.3 KB / 503.3 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ServiceScope..ctor(IResolverContext, IServiceScope)
new System.Threading.Tasks.Task • 302.0 KB
new System.Threading.Tasks.TaskCompletionSource • 100.7 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider • 100.7 KB
0.19% OpenScope • 469.8 KB / 469.8 KB • DryIoc.ResolverContext.OpenScope(IResolverContext, Object, Boolean, Boolean)
new DryIoc.Scope • 268.4 KB
new DryIoc.ResolverContext+<>c__DisplayClass11_0 • 100.7 KB
new System.Object • 100.7 KB
0.19% WithoutUnknownServiceResolver • 469.8 KB / 369.1 KB • DryIoc.Rules.WithoutUnknownServiceResolver(Rules+UnknownServiceResolver)
new DryIoc.Rules • 369.1 KB
0.04% RemoveAt • 100.7 KB / 100.7 KB • ImTools.ArrayTools.RemoveAt(T[], Int32)
new DryIoc.Rules+UnknownServiceResolver[] • 100.7 KB
0.16% b__0 • 402.7 KB / 402.7 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0.b__0(Rules)
new DryIoc.Rules+UnknownServiceResolver • 268.4 KB
new DryIoc.Rules+UnknownServiceResolver[] • 134.2 KB
0.15% WithCurrentScope • 369.1 KB / 369.1 KB • DryIoc.Container.WithCurrentScope(IScope, Boolean)
new DryIoc.Container • 369.1 KB
0.15% WithUnknownServiceResolvers • 369.1 KB / 369.1 KB • DryIoc.Rules.WithUnknownServiceResolvers(Rules+UnknownServiceResolver[])
new DryIoc.Rules • 369.1 KB
0.13% EnsureContingentPropertiesInitializedUnsafe • 334.9 KB / 334.9 KB • System.Threading.Tasks.Task.EnsureContingentPropertiesInitializedUnsafe()
new System.Threading.Tasks.Task+ContingentProperties • 334.9 KB
0.08% TryAddInternal • 201.0 KB / 201.0 KB • System.Collections.Concurrent.ConcurrentDictionary.TryAddInternal(TKey, Nullable, TValue, Boolean, Boolean, TValue)
new System.Collections.Concurrent.ConcurrentDictionary+Node • 201.0 KB
0.07% ContinueWithCore • 167.5 KB / 167.5 KB • System.Threading.Tasks.Task.ContinueWithCore(Task, TaskScheduler, CancellationToken, TaskContinuationOptions)
new System.Threading.Tasks.ContinueWithTaskContinuation • 167.5 KB
```
```
Totally allocated in sub-tree of : Microsoft.Azure.WebJobs.Host.Executors.FunctionInstance.get_InstanceServices()
Objects : 63456
Bytes : 2954960

1.14% get_InstanceServices • 2.82 MB / - • Microsoft.Azure.WebJobs.Host.Executors.FunctionInstance.get_InstanceServices()
1.14% CreateScope • 2.82 MB / - • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.CreateScope()
1.14% CreateChildScope • 2.82 MB / 142.5 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver.CreateChildScope(IServiceScopeFactory)
new System.Threading.Tasks.ContinuationResultTaskFromTask • 37.3 KB
new System.Func • 30.1 KB
new System.Func • 29.9 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0 • 26.4 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ServiceScope • 18.8 KB
0.85% UseInstance • 2.10 MB / 67.8 KB • DryIoc.Container.UseInstance(Type, Object, IfAlreadyRegistered, Boolean, Boolean, Object)
new DryIoc.Container+<>c__DisplayClass26_0 • 37.7 KB
new System.Func • 30.1 KB
0.83% Swap • 2.04 MB / 3.7 KB • ImTools.Ref.Swap(T, Func)
new System.SByte[] • 3.2 KB
new System.InvalidOperationException • 512 B
0.83% b__0 • 2.03 MB / 73.9 KB • DryIoc.Container+<>c__DisplayClass26_0.b__0(Container+Registry)
new DryIoc.Container+<>c__DisplayClass26_1 • 73.9 KB
0.40% AddOrUpdate • 997.3 KB / - • ImTools.ImHashMap.AddOrUpdate(K, V)
0.40% AddOrUpdate • 997.3 KB / 110.8 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 110.8 KB
0.35% AddOrUpdate • 886.5 KB / 110.8 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 110.8 KB
0.31% AddOrUpdate • 775.7 KB / 110.8 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 110.8 KB
0.26% AddOrUpdate • 664.9 KB / 110.8 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 110.8 KB
0.22% AddOrUpdate • 554.1 KB / 110.8 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 110.8 KB
0.18% AddOrUpdate • 443.3 KB / 110.8 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 110.8 KB
0.13% AddOrUpdate • 332.4 KB / 110.8 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 110.8 KB
0.09% AddOrUpdate • 221.6 KB / 221.6 KB • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap+Data • 110.8 KB
new ImTools.ImHashMap • 110.8 KB
0.30% SetOrAdd • 751.4 KB / - • DryIoc.Scope.SetOrAdd(Int32, Object)
0.25% TrackDisposable • 640.6 KB / 73.9 KB • DryIoc.Scope.TrackDisposable(IDisposable, Int32)
new DryIoc.Scope+<>c__DisplayClass19_0 • 73.9 KB
0.21% AddOrUpdateImpl • 535.7 KB / 118.4 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 118.4 KB
0.15% AddOrUpdateImpl • 380.0 KB / 93.0 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 93.0 KB
0.10% AddOrUpdateImpl • 252.0 KB / 87.1 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 87.1 KB
0.06% AddOrUpdateImpl • 141.4 KB / 72.3 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 72.3 KB
0.02% AddOrUpdateImpl • 60.9 KB / 45.2 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 45.2 KB
<0.01% AddOrUpdateImpl • 15.8 KB / 15.8 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 15.8 KB
<0.01% KeepBalance • 8.2 KB / 8.2 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 8.2 KB
<0.01% KeepBalance • 23.5 KB / 23.5 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 23.5 KB
0.01% KeepBalance • 35.0 KB / 35.0 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 35.0 KB
0.01% KeepBalance • 37.3 KB / 37.3 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 37.3 KB
0.01% KeepBalance • 31.0 KB / 31.0 KB • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 31.0 KB
0.04% AddOrUpdateImpl • 110.8 KB / 110.8 KB • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 110.8 KB
0.10% WithServices • 258.6 KB / 258.6 KB • DryIoc.Container+Registry.WithServices(ImHashMap)
new DryIoc.Container+Registry • 147.8 KB
new ImTools.Ref> • 55.4 KB
new ImTools.Ref>>> • 55.4 KB
0.05% CreateScope • 116.7 KB / 22.6 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.WebHostServiceProvider.CreateScope()
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceScope • 11.3 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider • 11.3 KB
0.02% OpenScope • 52.7 KB / 52.7 KB • DryIoc.ResolverContext.OpenScope(IResolverContext, Object, Boolean, Boolean)
new DryIoc.Scope • 30.1 KB
new DryIoc.ResolverContext+<>c__DisplayClass11_0 • 11.3 KB
new System.Object • 11.3 KB
0.02% WithCurrentScope • 41.4 KB / 41.4 KB • DryIoc.Container.WithCurrentScope(IScope, Boolean)
new DryIoc.Container • 41.4 KB
0.04% With • 105.4 KB / 52.7 KB • DryIoc.Container.With(Rules, IScopeContext, RegistrySharing, IScope)
new DryIoc.Container • 41.4 KB
new ImTools.Ref • 11.3 KB
0.02% WithoutCache • 52.7 KB / 52.7 KB • DryIoc.Container+Registry.WithoutCache()
new DryIoc.Container+Registry • 30.1 KB
new ImTools.Ref>>> • 11.3 KB
new ImTools.Ref> • 11.3 KB
0.02% .ctor • 56.5 KB / 56.5 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ServiceScope..ctor(IResolverContext, IServiceScope)
new System.Threading.Tasks.Task • 33.9 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider • 11.3 KB
new System.Threading.Tasks.TaskCompletionSource • 11.3 KB
0.02% OpenScope • 52.7 KB / 52.7 KB • DryIoc.ResolverContext.OpenScope(IResolverContext, Object, Boolean, Boolean)
new DryIoc.Scope • 30.1 KB
new System.Object • 11.3 KB
new DryIoc.ResolverContext+<>c__DisplayClass11_0 • 11.3 KB
0.02% WithoutUnknownServiceResolver • 52.7 KB / 41.4 KB • DryIoc.Rules.WithoutUnknownServiceResolver(Rules+UnknownServiceResolver)
new DryIoc.Rules • 41.4 KB
<0.01% RemoveAt • 11.3 KB / 11.3 KB • ImTools.ArrayTools.RemoveAt(T[], Int32)
new DryIoc.Rules+UnknownServiceResolver[] • 11.3 KB
0.02% b__0 • 45.2 KB / 45.2 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0.b__0(Rules)
new DryIoc.Rules+UnknownServiceResolver • 30.1 KB
new DryIoc.Rules+UnknownServiceResolver[] • 15.1 KB
0.02% WithCurrentScope • 41.4 KB / 41.4 KB • DryIoc.Container.WithCurrentScope(IScope, Boolean)
new DryIoc.Container • 41.4 KB
0.02% WithUnknownServiceResolvers • 41.4 KB / 41.4 KB • DryIoc.Rules.WithUnknownServiceResolvers(Rules+UnknownServiceResolver[])
new DryIoc.Rules • 41.4 KB
0.01% EnsureContingentPropertiesInitializedUnsafe • 37.3 KB / 37.3 KB • System.Threading.Tasks.Task.EnsureContingentPropertiesInitializedUnsafe()
new System.Threading.Tasks.Task+ContingentProperties • 37.3 KB
<0.01% TryAddInternal • 22.4 KB / 22.4 KB • System.Collections.Concurrent.ConcurrentDictionary.TryAddInternal(TKey, Nullable, TValue, Boolean, Boolean, TValue)
new System.Collections.Concurrent.ConcurrentDictionary+Node • 22.4 KB
<0.01% ContinueWithCore • 18.7 KB / 18.7 KB • System.Threading.Tasks.Task.ContinueWithCore(Task, TaskScheduler, CancellationToken, TaskContinuationOptions)
new System.Threading.Tasks.ContinueWithTaskContinuation • 18.7 KB
```
```
Totally allocated in sub-tree of : Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync(ActionContext)
Objects : 56296
Bytes : 3103059

1.20% ExecuteResultAsync • 2.96 MB / - • Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync(ActionContext)
1.20% GetRequiredService • 2.96 MB / - • Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider)
1.20% GetRequiredService • 2.96 MB / - • Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider, Type)
1.20% Resolve • 2.96 MB / - • DryIoc.Container.Resolve(Type, IfUnresolved)
1.20% ResolveAndCacheDefaultFactoryDelegate • 2.96 MB / 118.1 KB • DryIoc.Container.ResolveAndCacheDefaultFactoryDelegate(Type, IfUnresolved)
0.46% ResolveFactory • 1.12 MB / - • DryIoc.Container.ResolveFactory(Request)
0.28% b__2 • 708.6 KB / 560.9 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0.b__2(Request)
new DryIoc.FactoryDelegate • 236.2 KB
new DryIoc.DelegateFactory • 206.7 KB
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_1 • 118.1 KB
0.06% WithAsResolutionCall • 147.6 KB / - • DryIoc.Setup.WithAsResolutionCall()
0.06% MemberwiseClone • 147.6 KB / 147.6 KB • System.Object.MemberwiseClone()
new DryIoc.Setup+ServiceSetup • 147.6 KB
```
```
Totally allocated in sub-tree of : Microsoft.Azure.WebJobs.Script.WebHost.Middleware.FunctionInvocationMiddleware+d__2.MoveNext()
Objects : 624
Bytes : 35418

0.01% MoveNext • 34.6 KB / 2.4 KB • Microsoft.Azure.WebJobs.Script.WebHost.Middleware.FunctionInvocationMiddleware+d__2.MoveNext()
<0.01% ExecuteResultAsync • 9.9 KB / - • Microsoft.AspNetCore.Mvc.ObjectResult.ExecuteResultAsync(ActionContext)
<0.01% GetRequiredService • 9.9 KB / - • Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider)
<0.01% GetRequiredService • 9.9 KB / - • Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider, Type)
<0.01% Resolve • 9.9 KB / - • DryIoc.Container.Resolve(Type, IfUnresolved)
<0.01% ResolveAndCacheDefaultFactoryDelegate • 9.9 KB / 416 B • DryIoc.Container.ResolveAndCacheDefaultFactoryDelegate(Type, IfUnresolved)
<0.01% ResolveFactory • 4.0 KB / - • DryIoc.Container.ResolveFactory(Request)
<0.01% b__2 • 2.4 KB / 1.9 KB • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0.b__2(Request)
new DryIoc.FactoryDelegate • 832 B
new DryIoc.DelegateFactory • 728 B
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_1 • 416 B
<0.01% WithAsResolutionCall • 520 B / - • DryIoc.Setup.WithAsResolutionCall()
<0.01% MemberwiseClone • 520 B / 520 B • System.Object.MemberwiseClone()
new DryIoc.Setup+ServiceSetup • 520 B
```
```
Totally allocated in sub-tree of : Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx, FunctionStartedMessage, FunctionInstanceLogEntry, FunctionExecutor+ParameterHelper, ILogger, CancellationToken)
Objects : 500
Bytes : 30016

0.01% ExecuteWithLoggingAsync • 29.3 KB / - • Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx, FunctionStartedMessage, FunctionInstanceLogEntry, FunctionExecutor+ParameterHelper, ILogger, CancellationToken)
0.01% Start • 29.3 KB / - • System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start(TStateMachine)
0.01% MoveNext • 29.3 KB / 288 B • Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor+d__26.MoveNext()
<0.01% .ctor • 11.4 KB / - • Microsoft.Azure.WebJobs.Host.Bindings.FunctionBindingContext..ctor(IFunctionInstanceEx, CancellationToken)
<0.01% get_InstanceServices • 11.4 KB / - • Microsoft.Azure.WebJobs.Host.Executors.FunctionInstance.get_InstanceServices()
<0.01% CreateScope • 11.4 KB / - • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceProvider.CreateScope()
<0.01% CreateChildScope • 11.4 KB / 608 B • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver.CreateChildScope(IServiceScopeFactory)
new System.Threading.Tasks.ContinuationResultTaskFromTask • 160 B
new System.Func • 128 B
new System.Func • 128 B
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0 • 112 B
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ServiceScope • 80 B
<0.01% UseInstance • 8.4 KB / 288 B • DryIoc.Container.UseInstance(Type, Object, IfAlreadyRegistered, Boolean, Boolean, Object)
new DryIoc.Container+<>c__DisplayClass26_0 • 160 B
new System.Func • 128 B
<0.01% Swap • 8.1 KB / - • ImTools.Ref.Swap(T, Func)
<0.01% b__0 • 8.1 KB / 320 B • DryIoc.Container+<>c__DisplayClass26_0.b__0(Container+Registry)
new DryIoc.Container+<>c__DisplayClass26_1 • 320 B
<0.01% AddOrUpdate • 4.2 KB / - • ImTools.ImHashMap.AddOrUpdate(K, V)
<0.01% AddOrUpdate • 4.2 KB / 480 B • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 480 B
<0.01% AddOrUpdate • 3.8 KB / 480 B • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 480 B
<0.01% AddOrUpdate • 3.3 KB / 480 B • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 480 B
<0.01% AddOrUpdate • 2.8 KB / 480 B • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 480 B
<0.01% AddOrUpdate • 2.3 KB / 480 B • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 480 B
<0.01% AddOrUpdate • 1.9 KB / 480 B • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 480 B
<0.01% AddOrUpdate • 1.4 KB / 480 B • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap • 480 B
<0.01% AddOrUpdate • 960 B / 960 B • ImTools.ImHashMap.AddOrUpdate(Int32, K, V)
new ImTools.ImHashMap+Data • 480 B
new ImTools.ImHashMap • 480 B
<0.01% SetOrAdd • 2.5 KB / - • DryIoc.Scope.SetOrAdd(Int32, Object)
<0.01% TrackDisposable • 2.0 KB / 320 B • DryIoc.Scope.TrackDisposable(IDisposable, Int32)
new DryIoc.Scope+<>c__DisplayClass19_0 • 320 B
<0.01% AddOrUpdateImpl • 1.5 KB / 576 B • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 576 B
<0.01% AddOrUpdateImpl • 768 B / 384 B • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 384 B
<0.01% AddOrUpdateImpl • 384 B / 384 B • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 384 B
<0.01% KeepBalance • 192 B / 192 B • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 192 B
<0.01% KeepBalance • 192 B / 192 B • ImTools.ImMap.KeepBalance()
new ImTools.ImMap • 192 B
<0.01% AddOrUpdateImpl • 480 B / 480 B • ImTools.ImMap.AddOrUpdateImpl(Int32, V)
new ImTools.ImMap • 480 B
<0.01% WithServices • 1.1 KB / 1.1 KB • DryIoc.Container+Registry.WithServices(ImHashMap)
new DryIoc.Container+Registry • 640 B
new ImTools.Ref>>> • 240 B
new ImTools.Ref> • 240 B
<0.01% CreateScope • 496 B / 96 B • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.WebHostServiceProvider.CreateScope()
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.JobHostServiceScope • 48 B
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider • 48 B
<0.01% OpenScope • 224 B / 224 B • DryIoc.ResolverContext.OpenScope(IResolverContext, Object, Boolean, Boolean)
new DryIoc.Scope • 128 B
new System.Object • 48 B
new DryIoc.ResolverContext+<>c__DisplayClass11_0 • 48 B
<0.01% WithCurrentScope • 176 B / 176 B • DryIoc.Container.WithCurrentScope(IScope, Boolean)
new DryIoc.Container • 176 B
<0.01% With • 448 B / 224 B • DryIoc.Container.With(Rules, IScopeContext, RegistrySharing, IScope)
new DryIoc.Container • 176 B
new ImTools.Ref • 48 B
<0.01% WithoutCache • 224 B / 224 B • DryIoc.Container+Registry.WithoutCache()
new DryIoc.Container+Registry • 128 B
new ImTools.Ref> • 48 B
new ImTools.Ref>>> • 48 B
<0.01% .ctor • 240 B / 240 B • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ServiceScope..ctor(IResolverContext, IServiceScope)
new System.Threading.Tasks.Task • 144 B
new Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedServiceProvider • 48 B
new System.Threading.Tasks.TaskCompletionSource • 48 B
<0.01% OpenScope • 224 B / 224 B • DryIoc.ResolverContext.OpenScope(IResolverContext, Object, Boolean, Boolean)
new DryIoc.Scope • 128 B
new DryIoc.ResolverContext+<>c__DisplayClass11_0 • 48 B
new System.Object • 48 B
<0.01% WithoutUnknownServiceResolver • 224 B / 176 B • DryIoc.Rules.WithoutUnknownServiceResolver(Rules+UnknownServiceResolver)
new DryIoc.Rules • 176 B
<0.01% RemoveAt • 48 B / 48 B • ImTools.ArrayTools.RemoveAt(T[], Int32)
new DryIoc.Rules+UnknownServiceResolver[] • 48 B
<0.01% b__0 • 192 B / 192 B • Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection.ScopedResolver+<>c__DisplayClass12_0.b__0(Rules)
new DryIoc.Rules+UnknownServiceResolver • 128 B
new DryIoc.Rules+UnknownServiceResolver[] • 64 B
<0.01% WithCurrentScope • 176 B / 176 B • DryIoc.Container.WithCurrentScope(IScope, Boolean)
new DryIoc.Container • 176 B
<0.01% WithUnknownServiceResolvers • 176 B / 176 B • DryIoc.Rules.WithUnknownServiceResolvers(Rules+UnknownServiceResolver[])
new DryIoc.Rules • 176 B
<0.01% EnsureContingentPropertiesInitializedUnsafe • 160 B / 160 B • System.Threading.Tasks.Task.EnsureContingentPropertiesInitializedUnsafe()
new System.Threading.Tasks.Task+ContingentProperties • 160 B
<0.01% TryAddInternal • 96 B / 96 B • System.Collections.Concurrent.ConcurrentDictionary.TryAddInternal(TKey, Nullable, TValue, Boolean, Boolean, TValue)
new System.Collections.Concurrent.ConcurrentDictionary+Node • 96 B
<0.01% ContinueWithCore • 80 B / 80 B • System.Threading.Tasks.Task.ContinueWithCore(Task, TaskScheduler, CancellationToken, TaskContinuationOptions)
new System.Threading.Tasks.ContinueWithTaskContinuation • 80 B
```

...and about 20 more places it significantly allocates (happy to share the profiles and dive in with anyone). Overall though: it's a lot. In the current state, this path accounts for approximately 25-30% of our total allocations. We're paying in the cost to generate the tree on every invocation (a few times due to instance and request services) as well as the GC impact to follow-up.

#### Ideas
There are 2 sets of wins in play, small and large. For small, we could find a workaround to `scopedContext.UseInstance(scope.ServiceProvider);` that solves #5098, and maybe that's all that's immediately viable. However, the bigger win is a larger change.

@fabiocav and I have been discussing this a bit offline with the help of @sebastienros and I started progress on "What would removing DryIoc look like?" in #7969.

The approach in the PR mirrors Orchard's scoping approach by copying the services we need into a child scope (for the Job Host) and function calls themselves would only get a scope. The advantages are:
- It's tremendously simpler (we don't maintain a DI fork)
- Testing shows 80-100ms shaved off of cold start (@safihamid has numbers here)
- Request latency is lower (less work to do, and less GC pausing)
- 25-30% reduced allocations

However, and this is a big however, there's one big gotcha: `null` handling behavior. The built-in .NET provider has the behavior of failing to register a requested service failing (as most DI does). In DryIoc today though, we would _not_ fail based on a missing service, for example:
```cs
public class MyServiceA
{
public MyserviceA(SomeServiceB foo) { }
}
```
If a `MyServiceA` was registered but `SomeServiceB` was not there to resolve, we would not throw an exception. We sould pass `null` into the constructor above. This is because [our `ScopedServiceProvider`](https://github.com/Azure/azure-functions-host/blob/2fecc8b752ca60d0ef22b7c502c034a90e11a1b1/src/WebJobs.Script.WebHost/DependencyInjection/ScopedServiceProvider.cs) uses a specific overload of `IfUnresolved.ReturnDefault`:
```cs
public object GetService(Type serviceType)
{
return _resolver.Resolve(serviceType, IfUnresolved.ReturnDefault);
}
```

The way the .NET built-in DI behaves is that we'd throw an exception in this case: `System.InvalidOperationException : Unable to resolve service for type...`. This is not something we can override, it happens very deep in the call stack [here](https://github.com/dotnet/aspnetcore/blob/5adbdcb18ce1167321e919b930d575cbbfb7512c/src/Shared/ActivatorUtilities/ActivatorUtilities.cs#L376). What allows you to do this is have a default in your parameter that allows null, like this:
```cs
public class MyServiceA
{
public MyserviceA(SomeServiceB foo = null) { }
}
```
_That_ would be fine and what the built-in provider expects - it'd get a `null` there.

I think we're in agreement that exception is what _should_ happen and is a good thing, but it may be breaking for some users. The question is: how many people _would_ hit this? The good news is we can answer that, by adding telemetry where we return a default value today. [The plug point is here in `CreateExpressionOrDefault`](https://github.com/Azure/azure-functions-host/blob/2fecc8b752ca60d0ef22b7c502c034a90e11a1b1/src/WebJobs.Script.WebHost/DependencyInjection/DryIoc/Container.cs#L7084-L7090). If we log a metric here (possibly adding a `HashSet` if needed to not log more than once per type per app startup), we can tell how many users would be affected by effectively changing it to throw.

#### Status
The PR in #7969 is demonstrating the changes, but we need to look harder at the few tests failing. It looks like the tests may be incorrect and allowed to work via DryIoc before, but needs more investigation. I wanted to log this issue to give an overview of where we are and what wins are on the table in this path.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.