From 0e832d195a2ab672ac934f198f6f761b2985e7f3 Mon Sep 17 00:00:00 2001 From: Stephan Date: Tue, 25 Jul 2017 13:33:32 +0200 Subject: [PATCH] Benchmark dynamic ctors --- src/Umbraco.Tests.Benchmarks/App.config | 6 +- .../CtorInvokeBenchmarks.cs | 110 ++++++++++++++++++ src/Umbraco.Tests.Benchmarks/Program.cs | 1 + .../Umbraco.Tests.Benchmarks.csproj | 1 + 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs diff --git a/src/Umbraco.Tests.Benchmarks/App.config b/src/Umbraco.Tests.Benchmarks/App.config index d747fb6a61..7bf2e9f89d 100644 --- a/src/Umbraco.Tests.Benchmarks/App.config +++ b/src/Umbraco.Tests.Benchmarks/App.config @@ -1,6 +1,6 @@  - + @@ -10,7 +10,7 @@ - + @@ -55,6 +55,7 @@ + diff --git a/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs new file mode 100644 index 0000000000..7cce05c51d --- /dev/null +++ b/src/Umbraco.Tests.Benchmarks/CtorInvokeBenchmarks.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Horology; +using BenchmarkDotNet.Jobs; + +namespace Umbraco.Tests.Benchmarks +{ + [Config(typeof(Config))] + public class CtorInvokeBenchmarks + { + private class Config : ManualConfig + { + public Config() + { + Add(new MemoryDiagnoser()); + //Add(ExecutionValidator.FailOnError); + + //The 'quick and dirty' settings, so it runs a little quicker + // see benchmarkdotnet FAQ + Add(Job.Default + .WithLaunchCount(1) // benchmark process will be launched only once + .WithIterationTime(TimeInterval.FromMilliseconds(100)) // 100ms per iteration + .WithWarmupCount(3) // 3 warmup iteration + .WithTargetCount(3)); // 3 target iteration + } + } + + private ConstructorInfo _ctorInfo; + private Func _dynamicMethod; + private Func _expression; + private IFoo _foo = new Foo(null); + + [Setup] + public void Setup() + { + var ctorArgTypes = new[] { typeof(IFoo) }; + var type = typeof (Foo); + var constructor = _ctorInfo = type.GetConstructor(ctorArgTypes); + + if (constructor == null) + throw new Exception("Failed to get the ctor."); + + //IL_0000: ldarg.0 // this + //IL_0001: ldfld class Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks/IFoo Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks::_foo + //IL_0006: newobj instance void Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks/Foo::.ctor(class Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks/IFoo) + //IL_000b: pop + //IL_000c: ret + + var meth = new DynamicMethod(string.Empty, typeof(Foo), ctorArgTypes, type.Module, true); + var gen = meth.GetILGenerator(); + gen.Emit(OpCodes.Ldarg_0); + //gen.Emit(OpCodes.Call, constructor); + gen.Emit(OpCodes.Newobj, constructor); + gen.Emit(OpCodes.Ret); + _dynamicMethod = (Func) meth.CreateDelegate(typeof(Func)); + + var exprArg = Expression.Parameter(typeof(IFoo), "content"); + var exprNew = Expression.New(constructor, exprArg); + var expr = Expression.Lambda>(exprNew, exprArg); + _expression = expr.Compile(); + } + + public IFoo IlCtor(IFoo foo) + { + return new Foo(foo); + } + + [Benchmark] + public void DirectCtor() + { + var foo = new Foo(_foo); + } + + [Benchmark] + public void InvokeCtor() + { + var foo = _ctorInfo.Invoke(new object[] { _foo }); + } + + [Benchmark] + public void DynamicMethodCtor() + { + var foo = _dynamicMethod(_foo); + } + + [Benchmark] + public void ExpressionCtor() + { + var foo = _expression(_foo); + } + + public interface IFoo + { } + + public class Foo : IFoo + { + public Foo(IFoo foo) + { } + } + } +} diff --git a/src/Umbraco.Tests.Benchmarks/Program.cs b/src/Umbraco.Tests.Benchmarks/Program.cs index 2eac9ee419..d392c09992 100644 --- a/src/Umbraco.Tests.Benchmarks/Program.cs +++ b/src/Umbraco.Tests.Benchmarks/Program.cs @@ -14,6 +14,7 @@ namespace Umbraco.Tests.Benchmarks typeof(LinqCastBenchmarks), //typeof(DeepCloneBenchmarks), typeof(XmlPublishedContentInitBenchmarks), + typeof(CtorInvokeBenchmarks), }); switcher.Run(args); diff --git a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj index 5dc0d6fd3c..0a428b92e0 100644 --- a/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj +++ b/src/Umbraco.Tests.Benchmarks/Umbraco.Tests.Benchmarks.csproj @@ -164,6 +164,7 @@ +