|
|
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq.Expressions; |
|
using System.Reflection; |
|
using BenchmarkDotNet.Attributes; |
|
|
|
namespace Hyperion.Benchmarks |
|
{ |
|
public class HyperionConfig : ManualConfig |
|
{ |
|
public HyperionConfig() |
|
{ |
|
Add(StatisticColumn.Mean, StatisticColumn.Min, StatisticColumn.Max, StatisticColumn.OperationsPerSecond); |
|
Add(MarkdownExporter.GitHub); |
|
Add(MemoryDiagnoser.Default); |
|
} |
|
} |
|
|
|
[Config(typeof(HyperionConfig))] |
|
public class GeneralBenchmarks |
|
{ |
|
private Func<object, object> lambdaCtor; |
|
private ConstructorInfo ctorWithArgs; |
|
private MethodInfo addRangeInfo; |
|
private MethodInfo addInfo; |
|
private Action<object, object> addRange; |
|
private Action<object, object> add; |
|
private Type type; |
|
|
|
private DateTime[] data; |
|
|
|
[GlobalSetup] |
|
public void Setup() |
|
{ |
|
data = new[] |
|
{ |
|
new DateTime(2017, 11, 1, 12, 30, 11), |
|
new DateTime(2017, 11, 1, 12, 30, 11), |
|
new DateTime(2017, 11, 1, 12, 30, 11), |
|
new DateTime(2017, 11, 1, 12, 30, 11), |
|
new DateTime(2017, 11, 1, 12, 30, 11), |
|
new DateTime(2017, 11, 1, 12, 30, 11), |
|
}; |
|
type = typeof(List<DateTime>); |
|
ctorWithArgs = type.GetConstructor(new[] { typeof(IEnumerable<DateTime>) }); |
|
addRangeInfo = type.GetMethod("AddRange"); |
|
addRange = CompileMethod(addRangeInfo, typeof(IEnumerable<DateTime>)); |
|
addInfo = type.GetMethod("Add"); |
|
add = CompileMethod(addInfo, typeof(DateTime)); |
|
|
|
lambdaCtor = CompileCtor(ctorWithArgs); |
|
} |
|
|
|
private Func<object, object> CompileCtor(ConstructorInfo ctor) |
|
{ |
|
var arg = Expression.Parameter(typeof(object)); |
|
var castArg = Expression.Convert(arg, typeof(IEnumerable<DateTime>)); |
|
var call = Expression.New(ctor, new Expression[] { castArg }); |
|
var castRes = Expression.Convert(call, typeof(object)); |
|
var lambda = Expression.Lambda<Func<object, object>>(castRes, arg); |
|
var compiled = lambda.Compile(); |
|
return compiled; |
|
} |
|
|
|
private Action<object, object> CompileMethod(MethodInfo method, Type targetType) |
|
{ |
|
var instance = Expression.Parameter(typeof(object)); |
|
var arg = Expression.Parameter(typeof(object)); |
|
var castInstance = Expression.Convert(instance, typeof(List<DateTime>)); |
|
var castArg = Expression.Convert(arg, targetType); |
|
var call = Expression.Call(castInstance, method, new Expression[] { castArg }); |
|
var lambda = Expression.Lambda<Action<object, object>>(call, instance, arg); |
|
var compiled = lambda.Compile(); |
|
return compiled; |
|
} |
|
|
|
[Benchmark] |
|
public void ConstructorInfo_Invoke() |
|
{ |
|
var list = ctorWithArgs.Invoke(new object[] { data }); |
|
} |
|
|
|
[Benchmark] |
|
public void LambdaConstructor_Call() |
|
{ |
|
var list = lambdaCtor(data); |
|
} |
|
|
|
[Benchmark] |
|
public void Activator_plus_AddRange_Info() |
|
{ |
|
var list = Activator.CreateInstance(type, true); |
|
addRangeInfo.Invoke(list, new object[] { data }); |
|
} |
|
|
|
[Benchmark] |
|
public void Activator_plus_Add_Info() |
|
{ |
|
var list = Activator.CreateInstance(type, true); |
|
for (int i = 0; i < data.Length; i++) |
|
{ |
|
addInfo.Invoke(list, new object[] { data[i] }); |
|
} |
|
} |
|
|
|
[Benchmark] |
|
public void Activator_plus_AddRange_Lambda() |
|
{ |
|
var list = Activator.CreateInstance(type, true); |
|
addRangeInfo.Invoke(list, new object[] { data }); |
|
} |
|
|
|
[Benchmark] |
|
public void Activator_plus_Add_Lambda() |
|
{ |
|
var list = Activator.CreateInstance(type, true); |
|
for (int i = 0; i < data.Length; i++) |
|
{ |
|
addInfo.Invoke(list, new object[] { data[i] }); |
|
} |
|
} |
|
} |
|
} |