Saturday, November 26, 2016

10x faster than Delegate.DynamicInvoke

This is a follow up to my previous blog posts, Optimizing Dynamic Method Invokes in .NET, and Dynamically Invoke Methods Quickly, with InvokeHelpers.EfficientInvoke. Basically, I have re-implemented this for Tact.NET in a way that makes it smaller, faster, and compatible with the .NET Standard.

So, how much faster is this new way of doing things? EfficientInvoker.Invoke is over 10x faster than Delegate.DynamicInvoke, and 10x faster than MethodInfo.Invoke.

Check out the source on GitHub:

Simple Explanation

Here is an example of a method and a class that we might want to invoke dynamically...

public class Tester
{
    public bool AreEqual(int a, int b)
    {
        return a == b;
    }
}

...and then here is the code that the EfficientInvoker will generate at runtime to call that method:

public static object GeneratedFunction(object target, object[] args)
{
    return (object)((Tester)target).AreEqual((int)args[0], (int)args[1]);
}

See, it's simple!

Sample Tests

public class EfficientInvokerTest
{
    public void DelegateInvoke()
    {
        var del = (Delegate) new Func<int, int, bool>((a, b) => a == b);
            
        // Standard slow way
        var result1 = (bool)del.DynamicInvoke(1, 2);
        Assert.False(result1);
 
        // New 10x faster way
        var invoker = del.GetInvoker();
        var result2 = (bool)invoker.Invoke(del, 1, 2);
        Assert.False(result2);
    }
    
    public void MethodInvoke()
    {
        var tester = new Tester();
        var type = tester.GetType();
 
        // Standard slow way
        var methodInfo = type.GetTypeInfo().GetMethod("AreEqual");
        var result1 = (bool) methodInfo.Invoke(tester, new object[] {1, 2});
        Assert.False(result1);
 
        // New 10x faster way
        var invoker = type.GetMethodInvoker("AreEqual");
        var result2 = (bool) invoker.Invoke(tester, 1, 2);
        Assert.False(result2);
    }
    
    private class Tester
    {
        public bool AreEqual(int a, int b)
        {
            return a == b;
        }
    }
}

Enjoy,
Tom

8 comments:

  1. Hi, i cannot check the source on GitHub !
    any help?

    ReplyDelete
  2. https://github.com/tdupont750/tact.net/blob/master/framework/src/Tact/Reflection/EfficientInvoker.cs

    ReplyDelete
  3. Thankyou for this! I needed something super fast with minimal garbage. This looks like it does the job.

    ReplyDelete
  4. First of all, thank you for your post. Your posts are neatly organized with the information I want, so there are plenty of resources to reference. I bookmark this site and will find your posts frequently in the future. Thanks again ^^ 토토커뮤니티

    ReplyDelete
  5. If you are facing any challenges in arranging any place 토토사이트

    ReplyDelete
  6. Hello! Nice to meet you, I say . The name of the community I run is 먹튀검증사이트, and the community I run contains articles similar to your blog. If you have time, I would be very grateful if you visit my site .

    ReplyDelete
  7. What is this? That's a hell of a piece of news.토토사이트Can you tell me a secret next time? Thank you so much. Have a nice day.

    ReplyDelete
  8. We all need to see this kind of information, and we really hope that this article will spread widely.메이저안전놀이터 May the good things always be full.

    ReplyDelete

Real Time Web Analytics