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
Other Posts you might also like