Created
September 22, 2016 00:47
-
-
Save Sidneys1/ad64904fbc42a6b26beac73e67679d86 to your computer and use it in GitHub Desktop.
Benchmarking a Static Interface workaround using structs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Running; | |
namespace StaticInterfaceTest { | |
public interface IInterface { | |
int Run(); | |
} | |
public struct Explicit : IInterface { | |
[Benchmark, MethodImpl(MethodImplOptions.NoOptimization)] | |
int IInterface.Run() { | |
var i = 0; | |
for (; i < 100;) i++; | |
return i; | |
} | |
} | |
public struct Implicit : IInterface { | |
[Benchmark, MethodImpl(MethodImplOptions.NoOptimization)] | |
public int Run() { | |
var i = 0; | |
for (; i < 100;) i++; | |
return i; | |
} | |
} | |
public class Tester { | |
private readonly Func<int> _compiledImplicitTest; | |
private readonly Func<int> _compiledExplicitTest; | |
private readonly MethodInfo _explicitMethod; | |
private readonly MethodInfo _implicitMethod; | |
private readonly IInterface _dImplicit = default(Implicit); | |
private readonly IInterface _dExplicit = default(Explicit); | |
public Tester() { | |
var methodInfo = typeof(Tester).GetMethod(nameof(GenericRunner), BindingFlags.Static | BindingFlags.NonPublic); | |
_explicitMethod = methodInfo | |
.MakeGenericMethod(typeof(Explicit)); | |
_compiledExplicitTest = (Func<int>)_explicitMethod | |
.CreateDelegate(typeof(Func<int>)); | |
_implicitMethod = methodInfo | |
.MakeGenericMethod(typeof(Implicit)); | |
_compiledImplicitTest = (Func<int>)_implicitMethod | |
.CreateDelegate(typeof(Func<int>)); | |
} | |
[Benchmark(Description = "Implicit Interface default() Call", Baseline = true)] | |
public int ImplicitTest() => default(Implicit).Run(); | |
[Benchmark(Description = "Explicit Interface default() Call")] | |
public int ExplicitTest() => ((IInterface)default(Explicit)).Run(); | |
[Benchmark(Description = "Implicit Interface Instance Call")] | |
public int FieldImplicitTest() => _dImplicit.Run(); | |
[Benchmark(Description = "Explicit Interface Instance Call")] | |
public int FieldExplicitTest() => _dExplicit.Run(); | |
[Benchmark(Description = "Implicit Interface Generic Call")] | |
public int GenericImplicitTest() => GenericRunner<Implicit>(); | |
[Benchmark(Description = "Explicit Interface Generic Call")] | |
public int GenericExplicitTest() => GenericRunner<Explicit>(); | |
[Benchmark(Description = "Implicit Interface Runtime Delegate Call")] | |
public int ActionImplicitTest() => _compiledImplicitTest(); | |
[Benchmark(Description = "Explicit Interface Runtime Delegate Call")] | |
public int ActionExplicitTest() => _compiledExplicitTest(); | |
[Benchmark(Description = "Implicit Interface Runtime MethodInfo Invoke")] | |
public int MethodInfoImplicitTest() => (int)_implicitMethod.Invoke(null, null); | |
[Benchmark(Description = "Explicit Interface Runtime MethodInfo Invoke")] | |
public int MethodInfoExplicitTest() => (int)_explicitMethod.Invoke(null, null); | |
private static int GenericRunner<T>() where T : struct, IInterface => default(T).Run(); | |
} | |
internal class Program { | |
private static void Main() => BenchmarkRunner.Run<Tester>(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment