Skip to content

Instantly share code, notes, and snippets.

@Horusiath
Last active December 5, 2017 20:04
Show Gist options
  • Save Horusiath/0c89cfef85693b098b81ef0fb40b4346 to your computer and use it in GitHub Desktop.
Save Horusiath/0c89cfef85693b098b81ef0fb40b4346 to your computer and use it in GitHub Desktop.
Benchmarks for .NET collection creation
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] });
}
}
}
}
BenchmarkDotNet=v0.10.10, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i5-4430 CPU 3.00GHz (Haswell), ProcessorCount=4
Frequency=2929686 Hz, Resolution=341.3335 ns, Timer=TSC
.NET Core SDK=2.1.1
  [Host]     : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
  DefaultJob : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT

Method Mean Error StdDev Min Max Op/s Gen 0 Allocated
ConstructorInfo_Invoke 337.8 ns 1.9053 ns 1.7822 ns 334.5 ns 340.3 ns 2,960,186.6 0.0558 176 B
LambdaConstructor_Call 101.5 ns 0.4284 ns 0.3798 ns 100.8 ns 102.1 ns 9,853,714.5 0.0355 112 B
Activator_plus_AddRange_Info 395.3 ns 0.6649 ns 0.5894 ns 394.0 ns 396.1 ns 2,529,865.9 0.0558 176 B
Activator_plus_Add_Info 1,473.4 ns 6.8928 ns 6.4475 ns 1,463.3 ns 1,489.2 ns 678,701.8 0.2251 712 B
Activator_plus_AddRange_Lambda 396.4 ns 1.1750 ns 1.0991 ns 394.7 ns 398.7 ns 2,522,868.7 0.0558 176 B
Activator_plus_Add_Lambda 1,480.1 ns 3.2393 ns 2.8715 ns 1,474.7 ns 1,484.4 ns 675,621.2 0.2251 712 B
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment