|
using BenchmarkDotNet.Attributes; |
|
using BenchmarkDotNet.Configs; |
|
using BenchmarkDotNet.Jobs; |
|
using BenchmarkDotNet.Running; |
|
using System; |
|
using System.Linq; |
|
using System.Diagnostics; |
|
using System.Runtime.CompilerServices; |
|
|
|
namespace ConsoleApplication3 |
|
{ |
|
/// <summary> |
|
/// Use this to run slower but proven-to-be-accurate perf tests |
|
/// </summary> |
|
public class TestProofConfig : ManualConfig |
|
{ |
|
/// <summary> |
|
/// Instance of the config |
|
/// </summary> |
|
public static readonly IConfig Instance = new TestProofConfig(); |
|
|
|
/// <summary> |
|
/// Constructor |
|
/// </summary> |
|
public TestProofConfig() |
|
{ |
|
Add(new Job |
|
{ |
|
TargetCount = 10 |
|
}); |
|
} |
|
} |
|
|
|
class Program |
|
{ |
|
static void Main(string[] args) |
|
{ |
|
var sw = Stopwatch.StartNew(); |
|
CompareCallsBenchmark.CompareCalls(); |
|
|
|
Console.WriteLine(); |
|
Console.WriteLine("BenchmarkRunner, elapsed: " + sw.Elapsed); |
|
|
|
sw.Restart(); |
|
CompareCallsBenchmark.RunInline(); |
|
|
|
Console.WriteLine(); |
|
Console.WriteLine("RunInline, elapsed: " + sw.Elapsed); |
|
Console.ReadKey(); |
|
} |
|
} |
|
|
|
|
|
[Config(typeof(TestProofConfig))] |
|
public class CompareCallsBenchmark : CompareCallsBenchmark.ICompareCalls, CompareCallsBenchmark.ICompareCalls<int> |
|
{ |
|
public static void RunInline() |
|
{ |
|
var methods = |
|
(from m in typeof(CompareCallsBenchmark).GetMethods() |
|
where !m.IsStatic && Attribute.IsDefined(m, typeof(BenchmarkAttribute)) |
|
select (Func<CompareCallsBenchmark, int>)Delegate.CreateDelegate(typeof(Func<CompareCallsBenchmark, int>), m)) |
|
.ToArray(); |
|
|
|
var b = new CompareCallsBenchmark(); |
|
foreach (var method in methods) |
|
{ |
|
method(b); |
|
} |
|
} |
|
public static void CompareCalls() |
|
{ |
|
BenchmarkRunner.Run<CompareCallsBenchmark>(); |
|
} |
|
|
|
#region CompetitionMethods |
|
interface ICompareCalls |
|
{ |
|
int CallInterface(int a); |
|
int CallInterface<T>(int a); |
|
} |
|
interface ICompareCalls<T> |
|
{ |
|
T CallInterface(T a); |
|
} |
|
class CompareCallsDerived : CompareCallsBenchmark |
|
{ |
|
public override int CallVirtual(int a) |
|
{ |
|
return a + 1; |
|
} |
|
public override int CallInterface(int a) |
|
{ |
|
return a + 1; |
|
} |
|
public override int CallInterface<T>(int a) |
|
{ |
|
return a + 1; |
|
} |
|
} |
|
|
|
private static int Call(int a) |
|
{ |
|
return a + 1; |
|
} |
|
[MethodImpl(MethodImplOptions.NoInlining)] |
|
private static int CallNoInline(int a) |
|
{ |
|
return a + 1; |
|
} |
|
private static int Call<T>(int a) |
|
{ |
|
return a + 1; |
|
} |
|
|
|
private int CallInst(int a) |
|
{ |
|
return a + 1; |
|
} |
|
[MethodImpl(MethodImplOptions.NoInlining)] |
|
private int CallInstNoInline(int a) |
|
{ |
|
return a + 1; |
|
} |
|
private int CallInst<T>(int a) |
|
{ |
|
return a + 1; |
|
} |
|
|
|
public virtual int CallVirtual(int a) |
|
{ |
|
return a + 1; |
|
} |
|
public virtual int CallInterface(int a) |
|
{ |
|
return a + 1; |
|
} |
|
public virtual int CallInterface<T>(int a) |
|
{ |
|
return a + 1; |
|
} |
|
#endregion |
|
|
|
const int Count = 10 * 1000 * 1000; |
|
|
|
[Benchmark(Baseline = true)] |
|
public int M_00_Raw() |
|
{ |
|
int a = 0; |
|
for (int i = 0; i < Count; i++) a = a + 1; |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_01_Call() |
|
{ |
|
int a = 0; |
|
for (int i = 0; i < Count; i++) a = Call(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_02_GenericCall() |
|
{ |
|
int a = 0; |
|
for (int i = 0; i < Count; i++) a = Call<object>(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_03_InstanceCall() |
|
{ |
|
int a = 0; |
|
var p = new CompareCallsBenchmark(); |
|
for (int i = 0; i < Count; i++) a = p.CallInst(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_04_InstanceGenericCall() |
|
{ |
|
int a = 0; |
|
var p = new CompareCallsBenchmark(); |
|
for (int i = 0; i < Count; i++) a = p.CallInst<object>(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_05_CallNoInline() |
|
{ |
|
int a = 0; |
|
for (int i = 0; i < Count; i++) a = CallNoInline(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_06_InstanceCallNoInline() |
|
{ |
|
int a = 0; |
|
var p = new CompareCallsBenchmark(); |
|
for (int i = 0; i < Count; i++) a = p.CallInstNoInline(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_07_InstanceVirtualCall() |
|
{ |
|
int a = 0; |
|
var p = new CompareCallsBenchmark(); |
|
for (int i = 0; i < Count; i++) a = p.CallVirtual(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_08_DerivedVirtualCall() |
|
{ |
|
int a = 0; |
|
var p = new CompareCallsDerived(); |
|
for (int i = 0; i < Count; i++) a = p.CallVirtual(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_09_InterfaceCall() |
|
{ |
|
int a = 0; |
|
ICompareCalls p = new CompareCallsBenchmark(); |
|
for (int i = 0; i < Count; i++) a = p.CallInterface(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_10_DerivedInterfaceCall() |
|
{ |
|
int a = 0; |
|
ICompareCalls p = new CompareCallsDerived(); |
|
for (int i = 0; i < Count; i++) a = p.CallInterface(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_11_GenericInterfaceCall() |
|
{ |
|
int a = 0; |
|
ICompareCalls<int> p = new CompareCallsBenchmark(); |
|
for (int i = 0; i < Count; i++) a = p.CallInterface(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_12_DerivedGenericInterfaceCall() |
|
{ |
|
int a = 0; |
|
ICompareCalls<int> p = new CompareCallsDerived(); |
|
for (int i = 0; i < Count; i++) a = p.CallInterface(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_13_InterfaceGenericCall() |
|
{ |
|
int a = 0; |
|
ICompareCalls p = new CompareCallsBenchmark(); |
|
for (int i = 0; i < Count; i++) a = p.CallInterface<object>(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_14_DerivedInterfaceGenericCall() |
|
{ |
|
int a = 0; |
|
ICompareCalls p = new CompareCallsDerived(); |
|
for (int i = 0; i < Count; i++) a = p.CallInterface<object>(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_15_LambdaCached() |
|
{ |
|
int a1 = 0; |
|
Func<int, int> x = a => a + 1; |
|
for (int i = 0; i < Count; i++) a1 = x(a1); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_16_LambdaNew() |
|
{ |
|
int a1 = 0; |
|
for (int i = 0; i < Count; i++) |
|
{ |
|
Func<int, int> x = a => a + 1; |
|
a1 = x(a1); |
|
}; |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_17_LambdaClosure() |
|
{ |
|
int a1 = 0; |
|
var t = 0; |
|
for (int i = 0; i < Count; i++) |
|
{ |
|
t = 1; |
|
Func<int, int> x = a => a + t; |
|
a1 = x(a1); |
|
}; |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_18_LambdaClosureLocal() |
|
{ |
|
int a1 = 0; |
|
for (int i = 0; i < Count; i++) |
|
{ |
|
var t = 1; |
|
Func<int, int> x = a => a + t; |
|
a1 = x(a1); |
|
}; |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_19_FuncCached() |
|
{ |
|
int a = 0; |
|
Func<int, int> x = Call; |
|
for (int i = 0; i < Count; i++) a = x(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_20_FuncCachedInstance() |
|
{ |
|
int a = 0; |
|
Func<int, int> x = new CompareCallsBenchmark().CallInst; |
|
for (int i = 0; i < Count; i++) a = x(a); |
|
return Count; |
|
} |
|
[Benchmark] |
|
public int M_21_FuncNew() |
|
{ |
|
int a = 0; |
|
for (int i = 0; i < Count; i++) |
|
{ |
|
Func<int, int> x = Call; |
|
a = x(a); |
|
}; |
|
return Count; |
|
} |
|
} |
|
} |