Skip to content

Instantly share code, notes, and snippets.

@jonpryor
Forked from ermau/gist:3855949
Created October 22, 2012 17:07
Show Gist options
  • Save jonpryor/3932606 to your computer and use it in GitHub Desktop.
Save jonpryor/3932606 to your computer and use it in GitHub Desktop.
/*
## Mono JIT compiler version 2.10.9 (tarball Mon May 7 20:25:51 EDT 2012)
DynamicMethod creation: 0.0453009000ms
LINQ expressions creation: 0.0971724000ms
Delegate creation: 0.0044351000ms
DynamicMethod invocation: 0.0000612000ms
Expression invocation: 0.0000609000ms
MethodInfo invocation: 0.0007135000ms
Delegate invocation: 0.0000619000ms
Calls to reach even with MethodInfo:
DynamicMethod: 63.5768745620178
Expression: 136.276524176593
Delegate: 6.30273300630694
## Mono JIT compiler version 3.0.1 (master/3f4e46b Thu Oct 25 12:07:02 EDT 2012)
DynamicMethod creation: 0.0517962000ms
LINQ expressions creation: 0.1078764000ms
Delegate creation: 0.0037262000ms
DynamicMethod invocation: 0.0000492000ms
Expression invocation: 0.0000484000ms
MethodInfo invocation: 0.0008519000ms
Delegate invocation: 0.0000573000ms
Calls to reach even with MethodInfo:
DynamicMethod: 60.8585514731802
Expression: 126.687169855622
Delegate: 4.44124897288432
## .NET 4.5 w/ Windows 8 6.2.8400
DynamicMethod creation: 0.0090425000ms
LINQ expressions creation: 0.3854721000ms
Delegate creation: 0.0069054000ms
DynamicMethod invocation: 0.0000930000ms
Expression invocation: 0.0000917000ms
MethodInfo invocation: 0.0003422000ms
Delegate invocation: 0.0000697000ms
Calls to reach even with MethodInfo:
DynamicMethod: 26.6963763880768
Expression: 1126.7206312098
Delegate: 20.3831092928111
*/
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);
Action<PropertyInfo> createDelegate = p => Delegate.CreateDelegate (typeof(Func<Foo, object>), prop.GetGetMethod ());
double createDynamicTime = createDynamic.Timings (prop, 1000).Average (t => t.TotalMilliseconds);
double createExpressionTime = createExpr.Timings (prop, 1000).Average (t => t.TotalMilliseconds);
double createDelegateTime = createDelegate.Timings (prop, 1000).Average (t => t.TotalMilliseconds);
Console.WriteLine (" DynamicMethod creation:\t{0:N10}ms", createDynamicTime);
Console.WriteLine ("LINQ expressions creation:\t{0:N10}ms", createExpressionTime);
Console.WriteLine (" Delegate creation:\t{0:N10}ms", createDelegateTime);
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.GetGetMethod(), foo, 1000).Average (t => t.TotalMilliseconds);
Func<Foo, string> invokeDelegate = (Func<Foo, string>) Delegate.CreateDelegate (typeof(Func<Foo, string>), prop.GetGetMethod ());
Action<Foo> testDelegate = f => invokeDelegate (f);
double invokeDelegateTime = testDelegate.Timings (foo, 1000).Average (t => t.TotalMilliseconds);
Console.WriteLine();
Console.WriteLine ("DynamicMethod invocation:\t{0:N10}ms", getDyanmicTime);
Console.WriteLine (" Expression invocation:\t{0:N10}ms", getExpressionTime);
Console.WriteLine (" MethodInfo invocation:\t{0:N10}ms", getMethodTime);
Console.WriteLine (" Delegate invocation:\t{0:N10}ms", invokeDelegateTime);
Console.WriteLine();
Console.WriteLine ("Calls to reach even with MethodInfo:");
Console.WriteLine ("DynamicMethod:\t" + ((createDynamicTime + getDyanmicTime) / getMethodTime));
Console.WriteLine (" Expression:\t" + ((createExpressionTime + getExpressionTime) / getMethodTime));
Console.WriteLine (" Delegate:\t" + ((createDelegateTime + invokeDelegateTime) / 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.GetGetMethod ());
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