Skip to content

Commit

Permalink
Merge (#20)
Browse files Browse the repository at this point in the history
* Add a number of decorator-centric tests to demonstrate expected behavior around resolving IEnumerable<T> and T when decorators are in play
-- Exposes issue autofac#1113 in a number of skipped tests

* Adding a number of benchmarks for SingleInstance registrations with decorators
-- Altered base decorator benchmarks to perform multiple iterations to meansure repeats

* Benchmark tweaks to fix repetion issue and add lifetime scope to ensure each benchmark iteration actually creates instances on the first Resolve<> for the decorators

Co-authored-by: Bryan Dunn <vonogre@gmail.com>
Co-authored-by: Alistair Evans <alistairjevans@gmail.com>
  • Loading branch information
3 people committed May 9, 2020
1 parent e4f01e1 commit d1f3d7b
Show file tree
Hide file tree
Showing 8 changed files with 507 additions and 9 deletions.
7 changes: 6 additions & 1 deletion bench/Autofac.Benchmarks/Benchmarks.cs
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Autofac.Benchmarks.Decorators;

namespace Autofac.Benchmarks
Expand All @@ -15,14 +16,18 @@ internal static class Benchmarks
typeof(KeyedSimpleBenchmark),
typeof(KeylessGenericBenchmark),
typeof(KeylessNestedBenchmark),
typeof(KeylessNestedSharedInstanceBenchmark),
typeof(KeylessNestedLambdaBenchmark),
typeof(KeylessNestedSharedInstanceLambdaBenchmark),
typeof(KeylessSimpleBenchmark),
typeof(KeylessSimpleSharedInstanceBenchmark),
typeof(KeylessSimpleLambdaBenchmark),
typeof(KeylessSimpleSharedInstanceLambdaBenchmark),
typeof(DeepGraphResolveBenchmark),
typeof(EnumerableResolveBenchmark),
typeof(PropertyInjectionBenchmark),
typeof(RootContainerResolveBenchmark),
typeof(OpenGenericBenchmark)
};
}
}
}
43 changes: 37 additions & 6 deletions bench/Autofac.Benchmarks/Decorators/DecoratorBenchmarkBase.cs
Expand Up @@ -8,18 +8,49 @@ public abstract class DecoratorBenchmarkBase<TCommandHandler>
{
protected IContainer Container { get; set; }

[Benchmark(Baseline =true)]
public virtual void Baseline()
{
using (var scope = Container.BeginLifetimeScope())
{
//NO-OP for baseline measurement
}
}

[Benchmark]
public virtual void EnumerableResolve()
[Arguments(1)]
[Arguments(2)]
[Arguments(3)]
public virtual void ResolveEnumerableT(int repetitions)
{
var item = this.Container.Resolve<IEnumerable<TCommandHandler>>();
GC.KeepAlive(item);
using (var scope = Container.BeginLifetimeScope())
{
var iteration = 0;
object item = null;
while (iteration++ < repetitions)
{
item = scope.Resolve<IEnumerable<TCommandHandler>>();
GC.KeepAlive(item);
}
}
}

[Benchmark]
public virtual void SingleResolve()
[Arguments(1)]
[Arguments(2)]
[Arguments(3)]
public virtual void ResolveT(int repetitions)
{
var item = this.Container.Resolve<TCommandHandler>();
GC.KeepAlive(item);
using (var scope = Container.BeginLifetimeScope())
{
var iteration = 0;
object item = null;
while (iteration++ < repetitions)
{
item = scope.Resolve<TCommandHandler>();
GC.KeepAlive(item);
}
}
}
}
}
@@ -0,0 +1,28 @@
using Autofac.Benchmarks.Decorators.Scenario;
using BenchmarkDotNet.Attributes;

namespace Autofac.Benchmarks.Decorators
{
/// <summary>
/// Benchmarks a more complex case of chaining decorators using the new keyless syntax.
/// </summary>
public class KeylessNestedSharedInstanceBenchmark : DecoratorBenchmarkBase<ICommandHandler>
{
[GlobalSetup]
public void Setup()
{
var builder = new ContainerBuilder();

builder.RegisterType<CommandHandlerOne>()
.As<ICommandHandler>()
.InstancePerLifetimeScope();
builder.RegisterType<CommandHandlerTwo>()
.As<ICommandHandler>()
.InstancePerLifetimeScope();
builder.RegisterDecorator<CommandHandlerDecoratorOne, ICommandHandler>();
builder.RegisterDecorator<CommandHandlerDecoratorTwo, ICommandHandler>();

this.Container = builder.Build();
}
}
}
@@ -0,0 +1,30 @@
using Autofac.Benchmarks.Decorators.Scenario;
using BenchmarkDotNet.Attributes;

namespace Autofac.Benchmarks.Decorators
{
/// <summary>
/// Benchmarks a more complex case of chaining decorators using the new keyless syntax.
/// </summary>
public class KeylessNestedSharedInstanceLambdaBenchmark : DecoratorBenchmarkBase<ICommandHandler>
{
[GlobalSetup]
public void Setup()
{
var builder = new ContainerBuilder();

builder.RegisterType<CommandHandlerOne>()
.As<ICommandHandler>()
.InstancePerLifetimeScope();
builder.RegisterType<CommandHandlerTwo>()
.As<ICommandHandler>()
.InstancePerLifetimeScope();
builder.RegisterDecorator<ICommandHandler>(
(c, p, i) => new CommandHandlerDecoratorOne(i));
builder.RegisterDecorator<ICommandHandler>(
(c, p, i) => new CommandHandlerDecoratorTwo(i));

this.Container = builder.Build();
}
}
}
@@ -0,0 +1,27 @@
using Autofac.Benchmarks.Decorators.Scenario;
using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Generic;

namespace Autofac.Benchmarks.Decorators
{
/// <summary>
/// Benchmarks the shared instance case for decorators using the new keyless syntax.
/// </summary>
public class KeylessSimpleSharedInstanceBenchmark : DecoratorBenchmarkBase<ICommandHandler>
{
[GlobalSetup]
public void Setup()
{
var builder = new ContainerBuilder();
builder.RegisterType<CommandHandlerOne>()
.As<ICommandHandler>()
.InstancePerLifetimeScope();
builder.RegisterType<CommandHandlerTwo>()
.As<ICommandHandler>()
.InstancePerLifetimeScope();
builder.RegisterDecorator<CommandHandlerDecoratorOne, ICommandHandler>();
this.Container = builder.Build();
}
}
}
@@ -0,0 +1,27 @@
using Autofac.Benchmarks.Decorators.Scenario;
using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Generic;

namespace Autofac.Benchmarks.Decorators
{
/// <summary>
/// Benchmarks the shared instance case for decorators using the new keyless syntax.
/// </summary>
public class KeylessSimpleSharedInstanceLambdaBenchmark : DecoratorBenchmarkBase<ICommandHandler>
{
[GlobalSetup]
public void Setup()
{
var builder = new ContainerBuilder();
builder.RegisterType<CommandHandlerOne>()
.As<ICommandHandler>()
.InstancePerLifetimeScope();
builder.RegisterType<CommandHandlerTwo>()
.As<ICommandHandler>()
.InstancePerLifetimeScope();
builder.RegisterDecorator<ICommandHandler>((c, p, i) => new CommandHandlerDecoratorOne(i));
this.Container = builder.Build();
}
}
}
16 changes: 14 additions & 2 deletions bench/Autofac.Benchmarks/Harness.cs
@@ -1,4 +1,4 @@
// This software is part of the Autofac IoC container
// This software is part of the Autofac IoC container
// Copyright © 2011 Autofac Contributors
// https://autofac.org
//
Expand Down Expand Up @@ -56,15 +56,27 @@ public class Harness
[Fact]
public void Decorator_Keyless_Nested() => RunBenchmark<KeylessNestedBenchmark>();

[Fact]
public void Decorator_Keyless_Nested_Shared_Instance() => RunBenchmark<KeylessNestedSharedInstanceBenchmark>();

[Fact]
public void Decorator_Keyless_Nested_Lambda() => RunBenchmark<KeylessNestedLambdaBenchmark>();

[Fact]
public void Decorator_Keyless_Nested_Lambda_Shared_Instance() => RunBenchmark<KeylessNestedSharedInstanceLambdaBenchmark>();

[Fact]
public void Decorator_Keyless_Simple() => RunBenchmark<KeylessSimpleBenchmark>();

[Fact]
public void Decorator_Keyless_Simple_Shared_Instance() => RunBenchmark<KeylessSimpleSharedInstanceBenchmark>();

[Fact]
public void Decorator_Keyless_Simple_Lambda() => RunBenchmark<KeylessSimpleLambdaBenchmark>();

[Fact]
public void Decorator_Keyless_Simple_Lambda_Shared_Instance() => RunBenchmark<KeylessSimpleSharedInstanceLambdaBenchmark>();

[Fact]
public void DeepGraphResolve() => RunBenchmark<DeepGraphResolveBenchmark>();

Expand All @@ -91,4 +103,4 @@ private static void RunBenchmark<TBenchmark>()
BenchmarkRunner.Run(benchmarkType, new BenchmarkConfig());
}
}
}
}

0 comments on commit d1f3d7b

Please sign in to comment.