Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Speeding up Reflection Invoke C#/.NET

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.

like image 720
Rob Avatar asked Aug 25 '11 11:08

Rob


People also ask

Is there a way to speed up a method without reflection?

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.

How does reflection affect the execution speed of an application?

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.

What is the difference between fastmember and reflection?

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!

What is the use of reflection in C?

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.


2 Answers

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.

like image 70
Tim Rogers Avatar answered Sep 28 '22 05:09

Tim Rogers


Are you using C# 4? If so, dynamic may speed things up:

Action<object> hook = message => ((dynamic)handler).HandleMessage((dynamic)message);
like image 40
Gabe Avatar answered Sep 28 '22 04:09

Gabe