Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Dynamic Delegates with Expression Trees


:P
On this page:

Nate Kohari has a great post regarding nice dynamic delegate implementation using LINQ expression trees. Go check it out, it’s a great example of the power of Expression Trees in an example that is actually understandable and also very useful. I’ll wait here…

Basically what Nate’s code does is provide a dynamic method implementation for any generic method signature that you can provide via a MethodInfo structure.

So what? Dynamic invocation isn’t difficult, right? After all Reflection provides this functionality for us with simple code like this:

MethodInfo mi = inst.GetType().GetMethod("IndexOf", new Type[1] { typeof(string) });
object result = mi.Invoke(inst, new object[1] { "this" });

or if you want something more generic:

/// <summary>
/// Binding Flags constant to be reused for all Reflection access methods.
/// </summary>
public const BindingFlags MemberAccess =
    BindingFlags.Public | BindingFlags.NonPublic |
    BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase;
/// <summary>
/// Calls a method on an object dynamically. 
/// 
/// This version doesn't require specific parameter signatures to be passed. 
/// Instead parameter types are inferred based on types passed. Note that if 
/// you pass a null parameter, type inferrance cannot occur and if overloads
/// exist the call may fail. if so use the more detailed overload of this method.
/// </summary> 
/// <param name="instance">Instance of object to call method on</param>
/// <param name="method">The method to call as a stringToTypedValue</param>
/// <param name="parameterTypes">Specify each of the types for each parameter passed. 
/// You can also pass null, but you may get errors for ambiguous methods signatures
/// when null parameters are passed</param>
/// <param name="parms">any variable number of parameters.</param>        
/// <returns>object</returns>
public static object CallMethod(object instance, string method, params object[] parms)
{
    // Pick up parameter types so we can match the method properly
    Type[] parameterTypes = null;
    if (parms != null)
    {
        parameterTypes = new Type[parms.Length];
        for (int x = 0; x < parms.Length; x++)
        {
            // if we have null parameters we can't determine parameter types - exit
            if (parms[x] == null)
            {
                parameterTypes = null;  // clear out - don't use types        
                break;
            }
            parameterTypes[x] = parms[x].GetType();
        }
    }
    return CallMethod(instance, method, parameterTypes, parms);
}
/// <summary>
/// Calls a method on an object dynamically. This version requires explicit
/// specification of the parameter type signatures.
/// </summary>
/// <param name="instance">Instance of object to call method on</param>
/// <param name="method">The method to call as a stringToTypedValue</param>
/// <param name="parameterTypes">Specify each of the types for each parameter passed. 
/// You can also pass null, but you may get errors for ambiguous methods signatures
/// when null parameters are passed</param>
/// <param name="parms">any variable number of parameters.</param>        
/// <returns>object</returns>
public static object CallMethod(object instance, string method, Type[] parameterTypes, params object[] parms)
{
    if (parameterTypes == null && parms.Length > 0)
        // Call without explicit parameter types - might cause problems with overloads    
        // occurs when null parameters were passed and we couldn't figure out the parm type
        return instance.GetType().GetMethod(method, ReflectionUtils.MemberAccess | BindingFlags.InvokeMethod).Invoke(instance, parms);
    else
        // Call with parameter types - works only if no null values were passed
        return instance.GetType().GetMethod(method, ReflectionUtils.MemberAccess | BindingFlags.InvokeMethod, null,parameterTypes, null).Invoke(instance, parms);
}


which is maybe a little easier to work with:

int result = (int)ReflectionUtils.CallMethod(inst, "IndexOf", "this");

This works fine, but Reflection is on the slow side especially if you make repeated calls to the same method in a loop. Reflection can be an order of magnitude slower that early bound direct method calls, even though it’s still fairly quick. In a nutshell this means if you make a few Reflection calls to a method here or there it’s not worth fretting about. However, if you’re repeatedly calling code dynamically or your firing dynamic method calls in a loop, Reflection use can become a performance problem quickly.

One thing that can be done and reduces Reflection overhead significantly is to cache the MethodInfo structure – the retrieval of the method name as a string is actually very expensive. If you can hang on the MethodInfo instance and cache it performance improves significantly (somewhere around an 80% improvement in my simple tests with the String class).

Dynamic Invocation with LINQ Expressions

One of the really cool features of LINQ is the ability to create Expression Trees. Expression trees are in effect fancy code generators that allow you – among other things – to generate dynamic code on the fly. The idea is that you can basically construct the content of a delegate dynamically and then return the lamda expression (a delegate) back as a result. This sort of thing was possible prior to .NET 3.5 and LINQ, but it was a lot more cryptic as you had to use Reflection.Emit to generate and compile the code. Additionally high trust environments where required.

With Linq some of the trust issues have been reduced and the Expression syntax somewhat simplifies the process of creating the dynamic code. I’d be lying if I could say that I think that the Expression Tree syntax is easy, but at least I can read and follow it whereas Reflection.Emit code always felt like some foreign alphabet soup <g>.

Nate’s solution is nice because it’s very small and understandable and in the end result very fast. The basic concept is that there’s a generic delegate that can be applied against method signature:

public delegate object LateBoundMethod(object target, object[] arguments);

Coupled with a delegate factory class that can generate a generic delegate instance based on a MethodInfo structure passed to it. To use the delegate factory you’d do something like:

MethodInfo method = typeof(String).GetMethod("IndexOf", new Type[] { typeof(string) });




// create a dynamic delegate from the method
LateBoundMethod callback = DelegateFactory.Create(method);


for
(int i = 0; i < iterations; i++) { // call the method - repeatedly object result = callback(inst, new object[] { "this" }); }

I don’t want to rehash the whole code here as Nate does a good job of explaining what going on in his post. If you’ve gotten this far and you haven’t read it go read through his post and the code for the DelegateFactory. It may take a few passes over the Create() method, but you’ll get the idea of how the dynamic delegate code generation works.

So what? It’s fast – or is it?

The code above isn’t exactly inviting. It still takes a MethodInfo instance and calling of the factory method to create the delegate instance and if you want to effectively use this delegate you really have to cache it somewhere. So why go through all of this?

The reason is that performance of this dynamic delegate is very fast – if you use it more than a few times. Performance is – as you might expect – the same as if you had compiled delegate in your code, which is fairly close to direct early bound activation of the method.

Unfortunately the penalty is in the creation of the delegate which is fairly slow. In the code above running a few tests showed on my box the actual creation was taking nearly 4 milliseonds – which accounts for over 2000 invocations of the method. But once the delegate exists performance is excellent and pretty close to direct method invocation.

When I first read Nate’s post I was a little skeptical about the performance improvements that this might provide. Part of my thinking was that a lot of Reflection’s overhead comes from member lookups, but there’s also a lot of overhead for the actual method calls. In fact, I set up a few timing runs see what performance of the different scenarios looks like, which is interesting to compare:

[TestMethod]
public void
TestPerformanceRelative() { string inst = "test this sucka"; int iterations = 1000000; // *** Direct execution Stopwatch watch = new Stopwatch(); watch.Start(); for (int i = 0; i < iterations; i++) { int result = inst.IndexOf("this"); } watch.Stop(); this.Dump("Direct Invocation: " + watch.ElapsedMilliseconds.ToString()); // *** Using LateBoudndMethod watch.Reset(); watch.Start(); // get a method info MethodInfo method = typeof(String).GetMethod("IndexOf", new[] { typeof(string) }); LateBoundMethod callback = DelegateFactory.Create(method); // create a dynamic delegate from the method for (int i = 0; i < iterations; i++) { // call the method object result = callback(inst, new[] { "this" }); } watch.Stop(); this.Dump("Latebound Method: " + watch.ElapsedMilliseconds); //// Create lambda and compile each time - VERY, VERY SLOW! Don't do this! //watch.Reset(); //watch.Start(); //for (int i = 0; i < iterations; i++) //{ // LateBoundMethod callback2 = DelegateFactory.Create(method); // object result = callback2(inst, new [] { "this" }); //} //watch.Stop(); //this.Dump(watch.ElapsedMilliseconds); // *** Reflection with cached MethodInfo MethodInfo mi = inst.GetType().GetMethod("IndexOf", new Type[1] { typeof(string) }); watch.Reset(); watch.Start(); for (int i = 0; i < iterations; i++) { object result = mi.Invoke(inst, new object[1] { "this" }); } watch.Stop(); this.Dump("Method.Invoke (cached MethodInfo): " + watch.ElapsedMilliseconds.ToString()); // *** Reflection without cached MethodInfo watch.Reset(); watch.Start(); for (int i = 0; i < iterations; i++) { MethodInfo mi2 = inst.GetType().GetMethod("IndexOf", new Type[1] { typeof(string) }); object result = mi2.Invoke(inst, new object[1] { "this" }); } watch.Stop(); this.Dump("Method.Invoke with type retrieved each time): " + watch.ElapsedMilliseconds.ToString()); // *** Reflection using Type.InvokeMember watch.Reset(); watch.Start(); for (int i = 0; i < iterations; i++) { object result = inst.GetType().InvokeMember("IndexOf", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, inst, new object[1] { "this" }); } watch.Stop(); this.Dump("Reflection InvokeMember: " + watch.ElapsedMilliseconds.ToString()); // *** Using ReflectionUtils.CallMethod watch.Reset(); watch.Start(); for (int i = 0; i < iterations; i++) { // call the method object result = ReflectionUtils.CallMethod(inst, "IndexOf", "this"); } watch.Stop(); this.Dump("ReflectionUtils.CallMethod (no explicit parameters): " + watch.ElapsedMilliseconds); // *** Using ReflectionUtils.CallMethod with parameter types provided watch.Reset(); watch.Start(); for (int i = 0; i < iterations; i++) { // call the method object result = ReflectionUtils.CallMethod(inst, "IndexOf", new Type[1] { typeof(string) }, "this"); } watch.Stop(); this.Dump("ReflectionUtils.CallMethod (parm types provided): " + watch.ElapsedMilliseconds.ToString()); }

The result from this execution with one million iterations in milliseconds is:

Direct Invocation: 151
Latebound Method: 197
Method.Invoke (cached MethodInfo): 1474
Method.Invoke (MethodInfo retrieved each time): 2597
Reflection InvokeMember: 5533
ReflectionUtils.CallMethod (no explicit parameters): 3073
ReflectionUtils.CallMethod (parm types provided): 3024

Impressive - the Latebound code is clearly in the ballpark for many iterations, where the nearest Reflection based approach is almost 10 times as slow as direct invokation.

But it’s not as simple as that. Remember that there’s a startup penalty for creating, parsing and compiling the Expression Tree. If I run the same set of tests with only 1 or 10 invocations I get these results (ticks might be better but you can see the problem here quite clearly):

Direct Invocation: 0
Latebound Method: 4
Method.Invoke (cached MethodInfo): 0
Method.Invoke with type retrieved each time): 0
Reflection InvokeMember: 0
ReflectionUtils.CallMethod (no explicit parameters): 0
ReflectionUtils.CallMethod (parm types provided): 0

Even the single creation/compilation of the Expression Tree results in a 4 millisecond hit. It takes to about 2000-3000 iterations before the performance gain starts doing better than cached MethodInfo.Invoke. Here’s at 2500 iterations:

Direct Invocation: 0
Latebound Method: 4
Method.Invoke (cached MethodInfo): 4

Method.Invoke with type retrieved each time): 10
Reflection InvokeMember: 13
ReflectionUtils.CallMethod (no explicit parameters): 8
ReflectionUtils.CallMethod (parm types provided): 7

So, even with this method it’s not really clear cut of when you want to use the type of dynamic delegate generation code. It takes a fair amount of usage before the pre-compilation and expression tree parsing outweighs the slowness of Reflection. Even with  1000 iterations in the example above the slowest Reflection calling mechanism is still faster than even a single call of the dynamic delegate. If you look at the timing runs above I also created a loop creating the delegate each time the method is called and it sucked so bad I had to abort the run because it pegged one of the CPUs at 100%.

So clearly this is not something you’d want to use for one of dynamic method calls. THere’s nothing to be gained from that. The only way to get an advantage of this functionality is to cache the instance and reuse it frequently.

You can play around with the timings of the sample and the LateBound class. I’ve packaged this up into a single source file so all the classes mentioned are there for you to play with easily.

Download Code Sample

Posted in CSharp  

The Voices of Reason


 

Max
March 08, 2009

# re: Dynamic Delegates with Expression Trees

You could do the same with Reflection.Emit

Gates VP
March 08, 2009

# re: Dynamic Delegates with Expression Trees

Wow Rick, this is a tremendous amount of work that you did.

Thank you for sharing and elucidating.

ScobY9
March 08, 2009

# re: Dynamic Delegates with Expression Trees

i don't think this is particularly useful in real-life application because as you pointed out, it takes at least about 2500+ iterations to outperform MethodInfo.Invoke(). i think what makes reflection slow is not the actual invocation but rather the process of reading metadata and getting the MethodInfo. By the way MethodInfo is actually automatically cached using a strange mechanism, which means it might not hit the cache every time you call Type.GetMethod().

Alois Kraus
March 10, 2009

# re: Dynamic Delegates with Expression Trees

Hi Rick,

very nice post about the perf numbers. If you want to make your life easier when to measure the performance of method invocations I have some extension methods prepared which should help to ease such task:

http://geekswithblogs.net/akraus1/archive/2008/12/16/127989.aspx

Yours,
Alois Kraus

Rick Strahl
March 10, 2009

# re: Dynamic Delegates with Expression Trees

@Alois - nice extensions! Bookmarked for when I need it.

Ben Amada
March 10, 2009

# re: Dynamic Delegates with Expression Trees

The reflection / expression trees do mostly make sense after going over it a few times. Don't know if it will stick a few days from now :)

If anyone's looking for dynamic OrderBy functionality, a few months ago I ran across these very handy extension methods making use of expression trees and lambda expressions for dynamic OrderBy functionality. Haven't done any benchmarking of it, but they've come in very handy.

http://stackoverflow.com/questions/41244/dynamic-linq-orderby
( see response from Marc )

Jimmy Bogard
June 17, 2009

# More on Late-Bound Invocations with Expression Trees

Recently, I went on a bit of a tear in the AutoMapper trying to improve performance.  Besides the

Jeff Gabriels Pensieve
September 16, 2009

# Building General Purpose Lambda Expressions

I was fascinated a while back to find the use of the Expression class to build general purpose lambda

Gareth edwards
September 21, 2009

# re: Dynamic Delegates with Expression Trees

And another way -

--- 1 000 000 ---
Direct Invocation: 115
Latebound Method: 148
My way: 170
Method.Invoke (cached MethodInfo): 1000
Method.Invoke with type retrieved each time): 1752
Reflection InvokeMember: 3593
ReflectionUtils.CallMethod (no explicit parameters): 2129
ReflectionUtils.CallMethod (parm types provided): 2094


--- 1 ---
Direct Invocation: 0
Latebound Method: 5
My way: 1
Method.Invoke (cached MethodInfo): 0
Method.Invoke with type retrieved each time): 0
Reflection InvokeMember: 0
ReflectionUtils.CallMethod (no explicit parameters): 0
ReflectionUtils.CallMethod (parm types provided): 0

--- 2500 ---
Direct Invocation: 0
Latebound Method: 5
My way: 2
Method.Invoke (cached MethodInfo): 3
Method.Invoke with type retrieved each time): 4
Reflection InvokeMember: 10
ReflectionUtils.CallMethod (no explicit parameters): 5
ReflectionUtils.CallMethod (parm types provided): 5



        public static LateBoundMethod CreateDelegate(MethodInfo method)
        {
            ParameterInfo[] parameters = method.GetParameters();

            if (parameters.Length == 0) return CreateDelegate(method, parameters, typeof(Func<,>), typeof(GC<,>));
            if (parameters.Length == 1) return CreateDelegate(method, parameters, typeof(Func<,,>), typeof(GC<,,>));
            if (parameters.Length == 2) return CreateDelegate(method, parameters, typeof(Func<,,,>), typeof(GC<,,,>));

            throw new NotImplementedException("Not Implemented Yet.");
        }


        private static LateBoundMethod CreateDelegate(MethodInfo method, ParameterInfo[] parameters, Type typeOfDelegate, Type typeOfGC)
        {
            Type[] tParmas = new Type[parameters.Length + 2];
            for (int i = 0; i < parameters.Length; i++) tParmas[i + 1] = parameters[i].ParameterType;
            tParmas[0] = method.DeclaringType;
            tParmas[tParmas.Length - 1] = method.ReturnParameter.ParameterType;

            object func = Delegate.CreateDelegate(typeOfDelegate.MakeGenericType(tParmas), null, method);
            MethodInfo mCreateLateBoundMethod = typeOfGC.MakeGenericType(tParmas).GetMethod("CreateLateBoundMethod");
            return (LateBoundMethod)mCreateLateBoundMethod.Invoke(null, new object[] { func });
        }


        private static class GC<TIn1, TOut>
        {
            public static LateBoundMethod CreateLateBoundMethod(object delLoose)
            {
                var delTyit = (Func<TIn1, TOut>)delLoose;
                return (target, args) => delTyit((TIn1)target);
            }
        }
        private static class GC<TIn1, TIn2, TOut>
        {
            public static LateBoundMethod CreateLateBoundMethod(object delLoose)
            {
                var delTyit = (Func<TIn1, TIn2, TOut>)delLoose;
                return (target, args) => delTyit((TIn1)target, (TIn2)args[0]);
            }
        }
        private static class GC<TIn1, TIn2, TIn3, TOut>
        {
            public static LateBoundMethod CreateLateBoundMethod(object delLoose)
            {
                var delTyit = (Func<TIn1, TIn2, TIn3, TOut>)delLoose;
                return (target, args) => delTyit((TIn1)target, (TIn2)args[0], (TIn3)args[1]);
            }
        }


        public delegate object LateBoundMethod(object target, object[] arguments);
.


Delegate.CreateDelegate & Type.MakeGenericType are very powerful and I think they exist in the compactframework as well :-)
I should have used MethodInfo.MakeGenericMethod instead, to remove the need for mulitpal classes.

Kerem Kusmezer
November 18, 2009

# re: Dynamic Delegates with Expression Trees

Hi Rick,

I wrote a DynamicObject over the concept here , which allows you to access the properties of your object if it were DataTable row entries. I will post the final version very soon to your blog, i am caching the generated methods, so the bottleneck is really like nothing after you got the first instance.

Charles T
November 19, 2009

# re: Dynamic Delegates with Expression Trees

//Change lines like this:
this.Dump("Direct Invocation: " + watch.ElapsedMilliseconds.ToString());
 
//To this for more accurate output
this.Dump("Direct Invocation: " + ((watch.ElapsedTicks * 1000.0) / Stopwatch.Frequency).ToString());


Great article by the way!

Thanks!

Tjaart van Wijck
March 08, 2010

# re: Dynamic Delegates with Expression Trees

I this easily extensible to user a generic delegate?

What I'm looking for is a dynamic delegate wrapper for a generic method, where we start with a MethodInfo without a call to .MakeGenericMethod.

Any ideas?

Beni
July 26, 2010

# re: Dynamic Delegates with Expression Trees

Whats about using a method without a return value (void)?

Thanks!

www.dotnetwise.com
February 10, 2012

# re: Dynamic Delegates with Expression Trees

Still excellent after so many years!

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024