Skip to content

Instantly share code, notes, and snippets.

@AlbertoMonteiro
Created March 16, 2012 19:11
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 AlbertoMonteiro/2051920 to your computer and use it in GitHub Desktop.
Save AlbertoMonteiro/2051920 to your computer and use it in GitHub Desktop.
DynamicMethod with IL vs Delegate creation with Expression
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using FluentIL;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var typePessoa = typeof(Pessoa);
var typeString = typeof(string);
var spD = Stopwatch.StartNew();
var uia = IL.NewMethod()
.WithParameter(typePessoa)
.WithParameter(typeString)
.Returns(typeof(object))
.Ldarg(1)
.Ldstr("A")
.Ifeq()
.Ldarg(0)
.CallGet<Pessoa>("A")
.Box(typeof(object))
.Else()
.Ldarg(1)
.Ldstr("B")
.Ifeq()
.Ldarg(0)
.CallGet<Pessoa>("B")
.Box(typeof(object))
.Else()
.Ldstr("")
.Box(typeof(object))
.EndIf()
.EndIf()
.Ret();
var @delegate = (Func<Pessoa, string, object>)uia.AsDynamicMethod.CreateDelegate(typeof(Func<Pessoa, string, object>));
spD.Stop();
Console.WriteLine("IL Build time: {0}", spD.Elapsed);
spD = Stopwatch.StartNew();
var propertyInfo = typePessoa.GetProperty("A");
var getter = (Func<Pessoa, object>)CreateGetter(propertyInfo);
spD.Stop();
Console.WriteLine("Delegate Build time: {0}", spD.Elapsed);
var pessoa = new Pessoa { A = "10", B = "20" };
var delegateTimes = new List<TimeSpan>();
var ilTimes = new List<TimeSpan>();
for (var j = 0; j < 1000; j++)
{
var sp1 = Stopwatch.StartNew();
for (var i = 0; i < 1000000; i++)
{
var invoke = getter(pessoa);
}
sp1.Stop();
delegateTimes.Add(sp1.Elapsed);
var sp2 = Stopwatch.StartNew();
for (var i = 0; i < 1000000; i++)
{
var invoke = @delegate(pessoa, "A");
}
sp2.Stop();
ilTimes.Add(sp2.Elapsed);
}
Console.WriteLine("Delegate avg: {0}", delegateTimes.Average(span => span.Milliseconds));
Console.WriteLine("IL avg: {0}", ilTimes.Average(span => span.Milliseconds));
Console.Read();
}
public static Delegate CreateGetter(PropertyInfo property)
{
var objParm = Expression.Parameter(property.DeclaringType, "o");
Type delegateType = typeof(Func<,>).MakeGenericType(property.DeclaringType, typeof(object));
var lambda = Expression.Lambda(delegateType, Expression.Convert(Expression.Property(objParm, property.Name), typeof(object)), objParm);
return lambda.Compile();
}
}
public class Pessoa
{
public string A { get; set; }
public string B { get; set; }
}
}
@AlbertoMonteiro
Copy link
Author

A função retornada pela criação de delegate via expression é sempre mais rápida que a criação de dynamicmethod usando IL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment