There are plenty of posts on speeding up reflection invokes, examples here:
Speeding up Reflection API with delegate in .NET/C#
https://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/
and here:
Example : Speeding up Reflection API with delegate in .NET/C#
My question is about speeding up generic invokes. Is this possible at all?
I've got an abstract class and a class which implements it...
public abstract class EncasulatedMessageHandler<T> where T : Message
{
public abstract void HandleMessage(T message);
}
public class Handler : EncasulatedMessageHandler<MyMessageType>
{
public int blat = 0;
public override void HandleMessage(MyMessageType message) { blat++; }
}
What I want to do is build up a list of these message handler classes and quickly invoke their HandleMessage()
At the moment, I'm doing something that's approximately this:
object handler = Activator.CreateInstance(typeof(Handler)); // Ignore this, this is done up front.
MethodInfo method = type.GetMethod("HandleMessage", BindingFlags.Instance | BindingFlags.Public);
Action<object> hook = new Action<object>(delegate(object message)
{
method.Invoke(handler, new object[] { message });
});
// Then when I want to invoke it:
hook(new MyMessageType());
That's not the whole thing, but it's the important stuff...
The method.Invoke is very slow, I'd like to keep the generic parameters on the class, I realise I could lock this down to object and cast it in the HandleMessage method, but I'm trying to avoid doing this.
Is there anything I can do to speed this up? It's currently orders of magnitude slower than direct calls.
Any help would be appreciated.
Edit update: One thing comes to mind to really speed this up, but the coding overhead is massive: You can use dynamic code generation and compilation. That would mean dynamically building the source code that would call the method without reflection, dynamically compiling and executing this.
If you have fewer objects accessed with reflection you probably won't notice the execution speed of your code, but if you have higher load, especially if you have large collections and you are executing reflection in a loop, your application performances will be significantly lowered and you will notice the execution speed increases.
However this overhead is pretty small, FastMember is still way faster than Reflection and it’s very easy to use, so I recommend you take a look at it first. This option and all subsequent ones convert the reflection code into a delegate that can be directly invoked without the overhead of reflection every time, hence the speed boost!
This is an extremely useful feature in the strongly-typed languages like C#. When to use reflection? The main use of reflection is to inspect assemblies, types, and members of a class. It can be used whenever you are needed to determine contents of an unknown assembly, get all its dependencies or invoke methods by name.
Using Delegate.CreateDelegate()
should be a lot faster. You will end up with a pointer to the real function, not a delegate that calls Invoke()
.
Try this:
object handler = Activator.CreateInstance(typeof(Handler));
var handlerType = handler.GetType();
var method = handlerType.GetMethod("HandleMessage", BindingFlags.Instance | BindingFlags.Public);
var paramType = handlerType.GetGenericArguments()[0];
// invoke the MakeHandleMessageDelegate method dynamically with paramType as the type parameter
// NB we're only doing this once
Action<object> hook = (Action<object>) this.GetType().GetMethod("MakeHandleMessageDelegate")
.MakeGenericMethod(paramType)
.Invoke(null, new [] { handler });
In the same class add the following generic method. We invoke this dynamically above because we don't know the type parameter at compile time.
public static Action<object> MakeHandleMessageDelegate<T>(object target)
{
var d = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), target, "HandleMessage");
// wrap the delegate another that simply casts the object parameter to the required type
return param => d((T)param);
}
You then have a delegate that casts the parameter to the required type, then calls the HandleMessage
method.
Are you using C# 4? If so, dynamic
may speed things up:
Action<object> hook = message => ((dynamic)handler).HandleMessage((dynamic)message);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With