Describe the Bug
We were evaluating an autofac upgrade and found that our memory allocations shifted on service creation, I've been able to trace this to ResolvePipelineBuilder.BuildPipeline, since version 9.2 this uses a lamda that captures the resolve request context. versions 9.1 and before did not do this.
Steps to Reproduce
run this as a new console project linking either autofac <=9.1 or autofac >=9.2:
using Autofac;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
BenchmarkRunner.Run<ResolveAllocation>();
public interface IService { }
public sealed class Service : IService { }
public interface IDependency { }
public sealed class Dependency : IDependency { }
public interface IConsumer { }
public sealed class Consumer(IDependency dependency) : IConsumer { }
[MemoryDiagnoser]
public class ResolveAllocation
{
private IContainer _container = null!;
[GlobalSetup]
public void Setup()
{
var builder = new ContainerBuilder();
builder.RegisterType<Service>().As<IService>();
builder.RegisterType<Dependency>().As<IDependency>();
builder.RegisterType<Consumer>().As<IConsumer>();
_container = builder.Build();
}
[Benchmark(Baseline = true)]
public IService NoDependencies() => _container.Resolve<IService>();
[Benchmark]
public IConsumer OneDependency() => _container.Resolve<IConsumer>();
}
Expected Behavior
on autofac 9.1 I get:
| Method |
Mean |
Error |
StdDev |
Ratio |
RatioSD |
Gen0 |
Allocated |
Alloc Ratio |
| NoDependencies |
151.3 ns |
2.57 ns |
4.95 ns |
1.00 |
0.04 |
0.0663 |
832 B |
1.00 |
| OneDependency |
350.8 ns |
6.82 ns |
7.30 ns |
2.32 |
0.09 |
0.1063 |
1336 B |
1.61 |
but on autofac 9.2 I get:
| Method |
Mean |
Error |
StdDev |
Median |
Ratio |
RatioSD |
Gen0 |
Allocated |
Alloc Ratio |
| NoDependencies |
213.8 ns |
8.86 ns |
26.13 ns |
204.3 ns |
1.01 |
0.17 |
0.0839 |
1.03 KB |
1.00 |
| OneDependency |
431.6 ns |
8.60 ns |
13.40 ns |
429.2 ns |
2.05 |
0.25 |
0.1421 |
1.74 KB |
1.69 |
I expect the allocated number to be the same between versions.
Dependency Versions
9.1 -> 9.2 upgrade.
Additional Info
BuildMetricsMiddlewareChain is probably also affected in the same way.
The following is a fairly minimal patch that I was able to apply to 9.2/3 to recover the 9.1 allocation numbers, I didn't try to regression test against the rest of autofac, nor did I try to address the metrics chain:
diff --git a/src/Autofac/Core/Resolving/Pipeline/ResolvePipelineBuilder.cs b/src/Autofac/Core/Resolving/Pipeline/ResolvePipelineBuilder.cs
--- a/src/Autofac/Core/Resolving/Pipeline/ResolvePipelineBuilder.cs
+++ b/src/Autofac/Core/Resolving/Pipeline/ResolvePipelineBuilder.cs
@@ -174,13 +174,36 @@ private static ResolvePipeline BuildPipeline(MiddlewareDeclaration? lastDecl)
Action<ResolveRequestContext> BuildStandardMiddlewareChain(Action<ResolveRequestContext> next, IResolveMiddleware stage)
{
var stagePhase = stage.Phase;
- // Hot path when execution metrics are disabled.
- return context => ExecuteWithDiagnostics(context, stage, () =>
+ return context =>
{
- context.PhaseReached = stagePhase;
- stage.Execute(context, next);
- });
+ if (!context.DiagnosticSource.IsEnabled())
+ {
+ context.PhaseReached = stagePhase;
+ stage.Execute(context, next);
+ return;
+ }
+
+ context.DiagnosticSource.MiddlewareStart(context, stage);
+ var succeeded = false;
+ try
+ {
+ context.PhaseReached = stagePhase;
+ stage.Execute(context, next);
+ succeeded = true;
+ }
+ finally
+ {
+ if (succeeded)
+ {
+ context.DiagnosticSource.MiddlewareSuccess(context, stage);
+ }
+ else
+ {
+ context.DiagnosticSource.MiddlewareFailure(context, stage);
+ }
+ }
+ };
}
static void ExecuteWithDiagnostics(ResolveRequestContext context, IResolveMiddleware stage, Action action)
Describe the Bug
We were evaluating an autofac upgrade and found that our memory allocations shifted on service creation, I've been able to trace this to ResolvePipelineBuilder.BuildPipeline, since version 9.2 this uses a lamda that captures the resolve request context. versions 9.1 and before did not do this.
Steps to Reproduce
run this as a new console project linking either autofac <=9.1 or autofac >=9.2:
Expected Behavior
on autofac 9.1 I get:
but on autofac 9.2 I get:
I expect the allocated number to be the same between versions.
Dependency Versions
9.1 -> 9.2 upgrade.
Additional Info
BuildMetricsMiddlewareChain is probably also affected in the same way.
The following is a fairly minimal patch that I was able to apply to 9.2/3 to recover the 9.1 allocation numbers, I didn't try to regression test against the rest of autofac, nor did I try to address the metrics chain: