Skip to content

Instantly share code, notes, and snippets.

@pvginkel
Created January 30, 2018 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pvginkel/fed5c8512b9dfefc2870c6853bbfbf8b to your computer and use it in GitHub Desktop.
Save pvginkel/fed5c8512b9dfefc2870c6853bbfbf8b to your computer and use it in GitHub Desktop.
Benchmark for creating instances of value types through compiled LINQ expressions.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace ConsoleApp12
{
// The results of this benchmark on my machine are:
// Type | Method | Mean | Error | StdDev |
// ----------------------------------------------- |--------------- |----------:|----------:|----------:|
// ActivatorCreateInstanceBenchmark_Int64 | CreateInstance | 58.195 ns | 1.2360 ns | 1.1562 ns |
// ActivatorCreateInstanceBenchmark_MyLargeStruct | CreateInstance | 59.670 ns | 1.2297 ns | 1.6833 ns |
// ExpressionBenchmark_Int64 | CreateInstance | 4.062 ns | 0.1246 ns | 0.1105 ns |
// ExpressionBenchmark_MyLargeStruct | CreateInstance | 6.908 ns | 0.2018 ns | 0.2829 ns |
class Program
{
static void Main(string[] args)
{
var benchmarks = typeof(Program).Assembly
.GetTypes()
.Where(p => !p.IsAbstract && p.GetMethods().Any(p1 => p1.GetCustomAttributes(typeof(BenchmarkAttribute), true).Length > 0))
.OrderBy(p => p.FullName)
.ToArray();
new BenchmarkSwitcher(benchmarks).RunAllJoined();
}
// The implementation for the benchmark below is taken from:
//
// https://stackoverflow.com/questions/325426/programmatic-equivalent-of-defaulttype/12733445#12733445
//
public abstract class ExpressionBenchmark<T>
{
private readonly Func<object> _factory = GetDefaultValue(typeof(T));
private static Func<object> GetDefaultValue(Type type)
{
// Validate parameters.
if (type == null) throw new ArgumentNullException(nameof(type));
// We want an Func<object> which returns the default.
// Create that expression here.
Expression<Func<object>> e = Expression.Lambda<Func<object>>(
// Have to convert to object.
Expression.Convert(
// The default value, always get what the *code* tells us.
Expression.Default(type), typeof(object)
)
);
// Compile and return the value.
return e.Compile();
}
[Benchmark]
public object CreateInstance()
{
return _factory();
}
}
public class ExpressionBenchmark_Int64 : ExpressionBenchmark<long>
{
}
public class ExpressionBenchmark_MyLargeStruct : ExpressionBenchmark<MyLargeStruct>
{
}
public abstract class ActivatorCreateInstanceBenchmark<T>
{
private readonly Type _type = typeof(T);
[Benchmark]
public object CreateInstance()
{
return Activator.CreateInstance(_type);
}
}
public class ActivatorCreateInstanceBenchmark_Int64 : ActivatorCreateInstanceBenchmark<long>
{
}
public class ActivatorCreateInstanceBenchmark_MyLargeStruct : ActivatorCreateInstanceBenchmark<MyLargeStruct>
{
}
public struct MyLargeStruct
{
public long LongValue { get; set; }
public string StringValue { get; set; }
public int IntValue { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment