Skip to content

Instantly share code, notes, and snippets.

@davidfowl
Forked from jmangelo/gist:3173109
Created July 24, 2012 22:36
Show Gist options
  • Select an option

  • Save davidfowl/3173128 to your computer and use it in GitHub Desktop.

Select an option

Save davidfowl/3173128 to your computer and use it in GitHub Desktop.

Revisions

  1. davidfowl revised this gist Jul 24, 2012. 1 changed file with 35 additions and 11 deletions.
    46 changes: 35 additions & 11 deletions gistfile1.cs
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,9 @@
    using System;
    using System.Linq;
    using System.Diagnostics;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Collections.Generic;

    namespace ConsoleApplication3
    {
    @@ -20,10 +22,14 @@ static void Main(string[] args)
    Console.WriteLine();

    Console.WriteLine("Cached Delegate");
    var cache = Compile(mi);
    var cache = Compile<Action<A, int, int>>(mi);
    Time(() => cache.Invoke(new A(), 1, 2));
    Console.WriteLine();

    Console.WriteLine("Dynamic call site caching");
    Time(() => { dynamic d = new A(); d.Foo(1, 2); });
    Console.WriteLine();

    Console.WriteLine("Open Delegate");
    var od = CreateOpenDelegate(mi);
    Time(() => od.Invoke(new A(), 1, 2));
    @@ -40,18 +46,36 @@ private static void Time(Action a)
    Console.WriteLine(sw.Elapsed);
    }

    private static Action<A, int, int> Compile(MethodInfo mi)
    private static TDelegate Compile<TDelegate>(MethodInfo mi)
    {
    // Params
    var p1 = Expression.Parameter(typeof(A));
    var p2 = Expression.Parameter(typeof(int));
    var p3 = Expression.Parameter(typeof(int));
    ParameterExpression @this = null;
    if (!mi.IsStatic)
    {
    @this = Expression.Parameter(mi.DeclaringType, "this");
    }

    var parameters = new List<ParameterExpression>();
    if (@this != null)
    {
    parameters.Add(@this);
    }

    // Body
    var body = Expression.Call(p1, mi, p2, p3);
    foreach (var parameter in mi.GetParameters())
    {
    parameters.Add(Expression.Parameter(parameter.ParameterType, parameter.Name));
    }

    Expression call = null;
    if (@this != null)
    {
    call = Expression.Call(@this, mi, parameters.Skip(1));
    }
    else
    {
    call = Expression.Call(mi, parameters);
    }

    // compile
    return Expression.Lambda<Action<A, int, int>>(body, p1, p2, p3).Compile();
    return Expression.Lambda<TDelegate>(call, parameters).Compile();
    }

    private static Action<A, int, int> CreateOpenDelegate(MethodInfo mi)
    @@ -72,4 +96,4 @@ public void Foo(int a, int b)
    {
    }
    }
    }
    }
  2. @jmangelo jmangelo revised this gist Jul 24, 2012. 1 changed file with 17 additions and 1 deletion.
    18 changes: 17 additions & 1 deletion gistfile1.cs
    Original file line number Diff line number Diff line change
    @@ -22,6 +22,11 @@ static void Main(string[] args)
    Console.WriteLine("Cached Delegate");
    var cache = Compile(mi);
    Time(() => cache.Invoke(new A(), 1, 2));
    Console.WriteLine();

    Console.WriteLine("Open Delegate");
    var od = CreateOpenDelegate(mi);
    Time(() => od.Invoke(new A(), 1, 2));
    }

    private static void Time(Action a)
    @@ -48,6 +53,17 @@ private static Action<A, int, int> Compile(MethodInfo mi)
    // compile
    return Expression.Lambda<Action<A, int, int>>(body, p1, p2, p3).Compile();
    }

    private static Action<A, int, int> CreateOpenDelegate(MethodInfo mi)
    {
    var openDelegate = Delegate.CreateDelegate(
    typeof(Action<A, int, int>),
    null,
    mi,
    true);

    return (Action<A, int, int>)openDelegate;
    }
    }

    public class A
    @@ -56,4 +72,4 @@ public void Foo(int a, int b)
    {
    }
    }
    }
    }
  3. davidfowl created this gist Jul 24, 2012.
    59 changes: 59 additions & 0 deletions gistfile1.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,59 @@
    using System;
    using System.Diagnostics;
    using System.Linq.Expressions;
    using System.Reflection;

    namespace ConsoleApplication3
    {
    class Program
    {
    static void Main(string[] args)
    {
    var mi = typeof(A).GetMethod("Foo");

    Console.WriteLine("Regular method");
    Time(() => new A().Foo(1, 2));
    Console.WriteLine();

    Console.WriteLine("Invoke");
    Time(() => mi.Invoke(new A(), new object[] { 1, 2 }));
    Console.WriteLine();

    Console.WriteLine("Cached Delegate");
    var cache = Compile(mi);
    Time(() => cache.Invoke(new A(), 1, 2));
    }

    private static void Time(Action a)
    {
    var sw = Stopwatch.StartNew();
    for (int i = 0; i < 10000000; i++)
    {
    a();
    }
    sw.Stop();
    Console.WriteLine(sw.Elapsed);
    }

    private static Action<A, int, int> Compile(MethodInfo mi)
    {
    // Params
    var p1 = Expression.Parameter(typeof(A));
    var p2 = Expression.Parameter(typeof(int));
    var p3 = Expression.Parameter(typeof(int));

    // Body
    var body = Expression.Call(p1, mi, p2, p3);

    // compile
    return Expression.Lambda<Action<A, int, int>>(body, p1, p2, p3).Compile();
    }
    }

    public class A
    {
    public void Foo(int a, int b)
    {
    }
    }
    }