Last active
February 1, 2017 12:27
-
-
Save tmakin/e47601befdd9e502485ab729dcf1f83f to your computer and use it in GitHub Desktop.
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
//Source: https://codeblog.jonskeet.uk/2011/08/22/optimization-and-generics-part-1-the-new-constraint/ | |
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Linq.Expressions; | |
using System.Reflection; | |
#pragma warning disable 0169 | |
public class SmallClass { int x; } | |
public class LargeClass { long a, b, c, d, e, f, g, h; } | |
public struct SmallStruct { int x; } | |
public struct LargeStruct { long a, b, c, d, e, f, g, h; } | |
#pragma warning restore 0169 | |
public class Benchmark | |
{ | |
static Action[] Tests = | |
{ | |
SmallStructFromExpression, | |
SmallStructWithConstraint, | |
SmallStructWithProvider, | |
LargeStructFromExpression, | |
LargeStructWithConstraint, | |
LargeStructWithProvider, | |
SmallClassFromExpression, | |
SmallClassWithConstraint, | |
SmallClassWithProvider, | |
LargeClassFromExpression, | |
LargeClassWithConstraint, | |
LargeClassWithProvider, | |
}; | |
private static Func<SmallStruct> smallStructConstructor = GetCtor<SmallStruct>(); | |
private static Func<SmallClass> smallClassConstructor = GetCtor<SmallClass>(); | |
private static Func<LargeStruct> largeStructConstructor = GetCtor<LargeStruct>(); | |
private static Func<LargeClass> largeClassConstructor = GetCtor<LargeClass>(); | |
private static Func<T> GetCtor<T>() | |
{ | |
Type type = typeof(T); | |
Expression body = Expression.New(type); | |
return Expression.Lambda<Func<T>>(body).Compile(); | |
} | |
private static void SmallStructWithConstraint() | |
=> MakeInstance<SmallStruct>(); | |
private static void SmallStructWithProvider() | |
=> MakeInstance<SmallStruct>(() => new SmallStruct()); | |
private static void SmallStructFromExpression() | |
=> MakeInstance<SmallStruct>(smallStructConstructor); | |
private static void LargeStructWithConstraint() | |
=> MakeInstance<LargeStruct>(); | |
private static void LargeStructWithProvider() | |
=> MakeInstance<LargeStruct>(() => new LargeStruct()); | |
private static void LargeStructFromExpression() | |
=> MakeInstance<LargeStruct>(largeStructConstructor); | |
private static void SmallClassWithConstraint() | |
=> MakeInstance<SmallClass>(); | |
private static void SmallClassWithProvider() | |
=> MakeInstance<SmallClass>(() => new SmallClass()); | |
private static void SmallClassFromExpression() | |
=> MakeInstance<SmallClass>(smallClassConstructor); | |
private static void LargeClassWithConstraint() | |
=> MakeInstance<LargeClass>(); | |
private static void LargeClassWithProvider() | |
=> MakeInstance<LargeClass>(() => new LargeClass()); | |
private static void LargeClassFromExpression() | |
=> MakeInstance<LargeClass>(largeClassConstructor); | |
private static void MakeInstance<T>() where T : new() | |
{ | |
T t = new T(); | |
UseValue(t); | |
} | |
private static void MakeInstance<T>(Func<T> provider) where T : new() | |
{ | |
T t = provider(); | |
UseValue(t); | |
} | |
private static void UseValue<T>(T instance) | |
{ | |
// Do nothing... | |
} | |
// -------------- INFRASTRUCTURE BELOW HERE -------------- | |
const int Iterations = 100000000; | |
static void Main() | |
{ | |
Console.WriteLine("Environment: CLR {0} on {1}", Environment.Version, Environment.OSVersion); | |
// Warm up | |
RunTests(1, false, 0); | |
int maxMethodLength = Tests.Select(x => x.Method.Name.Length).Max(); | |
// Real thing | |
RunTests(Iterations, true, maxMethodLength); | |
} | |
static void RunTests(int count, bool displayResults, int maxLength) | |
{ | |
foreach (Action action in Tests) | |
{ | |
Stopwatch sw = Stopwatch.StartNew(); | |
for (int i = 0; i < count; i++) | |
{ | |
action(); | |
} | |
sw.Stop(); | |
if (displayResults) | |
{ | |
Console.WriteLine("{0}: {1}ms", action.Method.Name.PadRight(maxLength), | |
((int)sw.ElapsedMilliseconds).ToString().PadLeft(6)); | |
} | |
GC.Collect(); | |
GC.WaitForPendingFinalizers(); | |
GC.Collect(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment