Skip to content

Instantly share code, notes, and snippets.

@ermau
Created October 9, 2012 01:04
Show Gist options
  • Save ermau/3855949 to your computer and use it in GitHub Desktop.
Save ermau/3855949 to your computer and use it in GitHub Desktop.
/*
DynamicMethod creation: 0.0053597000ms
LINQ expressions creation: 0.1050939000ms
DynamicMethod invocation: 0.0000474000ms
Expression invocation: 0.0000450000ms
MethodInfo invocation: 0.0002190000ms
Calls to reach even with MethodInfo:
DynamicMethod: 24.6899543379
Expression: 480.086301369866
*/
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using Cadenza;
namespace Getter
{
static class Program
{
static void Main(string[] args)
{
PropertyInfo prop = typeof (Foo).GetProperty ("Name");
//Console.WriteLine (CreateDynamicMethodDelegate (prop) (new Foo { Name = "bar " }));
//Console.WriteLine (CreateGetPropertyDelegate (prop) (new Foo { Name = "bar " }));
Action<PropertyInfo> createDynamic = p => CreateDynamicMethodDelegate (p);
Action<PropertyInfo> createExpr = p => CreateGetPropertyDelegate (p);
double createDynamicTime = createDynamic.Timings (prop, 1000).Average (t => t.TotalMilliseconds);
double createExpressionTime = createExpr.Timings (prop, 1000).Average (t => t.TotalMilliseconds);
Console.WriteLine ("DynamicMethod creation: {0:N10}ms", createDynamicTime);
Console.WriteLine ("LINQ expressions creation: {0:N10}ms", createExpressionTime);
Foo foo = new Foo { Name = "bar" };
Func<object, object> getNameDynamic = CreateDynamicMethodDelegate (prop);
Action<Func<object, object>, Foo> testDynamic = (d, o) => d (o);
double getDyanmicTime = testDynamic.Timings (getNameDynamic, foo, 1000).Average (t => t.TotalMilliseconds);
Func<object, object> getNameExpression = CreateDynamicMethodDelegate (prop);
Action<Func<object, object>, Foo> testExpression = (d, o) => d (o);
double getExpressionTime = testExpression.Timings (getNameExpression, foo, 1000).Average (t => t.TotalMilliseconds);
Action<MethodInfo, Foo> testMethod = (m, f) => m.Invoke (f, null);
double getMethodTime = testMethod.Timings (prop.GetMethod, foo, 1000).Average (t => t.TotalMilliseconds);
Console.WriteLine();
Console.WriteLine ("DynamicMethod invocation: {0:N10}ms", getDyanmicTime);
Console.WriteLine ("Expression invocation: {0:N10}ms", getExpressionTime);
Console.WriteLine ("MethodInfo invocation: {0:N10}ms", getMethodTime);
Console.WriteLine();
Console.WriteLine ("Calls to reach even with MethodInfo:");
Console.WriteLine ("DynamicMethod: " + ((createDynamicTime + getDyanmicTime) / getMethodTime));
Console.WriteLine ("Expression: " + ((createExpressionTime + getExpressionTime) / getMethodTime));
}
private static Func<object, object> CreateDynamicMethodDelegate (PropertyInfo prop)
{
DynamicMethod method = new DynamicMethod ("name", typeof(object), new[] { typeof (object) });
ILGenerator gen = method.GetILGenerator();
gen.Emit (OpCodes.Ldarg_0);
gen.Emit (OpCodes.Castclass, prop.DeclaringType);
gen.Emit (OpCodes.Callvirt, prop.GetMethod);
gen.Emit (OpCodes.Ret);
return (Func<object,object>)method.CreateDelegate (typeof (Func<object, object>));
}
private static Func<object, object> CreateGetPropertyDelegate (PropertyInfo prop)
{
var instance = Expression.Parameter(typeof(object), "instance");
var instCast = prop.GetGetMethod(true).IsStatic ? null : Expression.Convert(instance, prop.ReflectedType);
var propAcc = Expression.Property(instCast, prop);
var castProp = Expression.Convert(propAcc, typeof(object));
var lambda = Expression.Lambda<Func<object, object>> (castProp, instance);
return lambda.Compile();
}
}
public class Foo
{
public string Name
{
get;
set;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment