Created
March 16, 2012 19:11
-
-
Save AlbertoMonteiro/2051920 to your computer and use it in GitHub Desktop.
DynamicMethod with IL vs Delegate creation with Expression
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
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; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A função retornada pela criação de delegate via expression é sempre mais rápida que a criação de dynamicmethod usando IL