1

I recently saw that you can convert a MethodInfo into a Delegate. But sometimes you may not know what exactly its params or type is. So thats where Delegate.DynamicInvoke comes into play.

But whats the difference between MethodInfo.Invoke and Delegate.DynamicInvoke? Which is faster and which produces less GC alloc calls ?

genaray
  • 1,080
  • 1
  • 9
  • 30
  • Does this answer your question? [Difference Between Invoke and DynamicInvoke](https://stackoverflow.com/questions/12858340/difference-between-invoke-and-dynamicinvoke) – Lolop Mar 31 '21 at 12:56
  • @Lolop No :/ It justs the difference between Delegate.Invoke and Delegate.DynamicInvoke. Furthermore no word of the garbage created – genaray Mar 31 '21 at 12:58
  • Are you asking what the difference between `Delegate.DynamicInvoke` and `MethodInfo.Invoke` is? Your title says that, but from your actual question it sounded to me like you were converting your `MethodInfo` into a delegate, and wanted to know the difference between `Delgate.Invoke` and `Delegate.DynamicInvoke`. – Lolop Mar 31 '21 at 13:05
  • 1
    Either way, this would be a good opportunity to benchmark it yourself using [Benchmark.Net](https://benchmarkdotnet.org/articles/overview.html). – Lolop Mar 31 '21 at 13:07

1 Answers1

2

Curiosity did get the better of me so I ended up benchmarking it myself. I still recommend doing it yourself to give it a go and see if you get the same results. If you had a specific situation in mind that might yield different results.

Results

I was kind of surprised at first, but here they are. I added in a standard Delegate.Invoke just to compare.

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
MethodInfoInvoke 116.9913 ns 1.0848 ns 1.0148 ns 0.0024 - - 40 B
DelegateDynamicInvoke 391.8141 ns 6.6877 ns 6.2557 ns 0.0105 - - 176 B
DelegateInvoke 0.4334 ns 0.0037 ns 0.0033 ns - - - -

As you can see, MethodInfo.Invoke is much better than Delegate.DynamicInvoke.

This is without considering the cost of converting the MethodInfo into a Delegate in the first place. Also the MethodInfo can just be used on any instance, whereas Delegate.DynamicInvoke is locked to a specific instance (Could be wrong on that though, I haven't used CreateDelegate before).

And lastly you need to pass the delegate type to CreateDelegate, which wouldn't always be easy.

So for less work, you get faster invocation and less garbage generated by using MethodInfo.Invoke.

Benchmark Code

[MemoryDiagnoser]
public class Benchmark
{
    private MethodInfo MethodInfo { get; set; }
    private Delegate MethodDynamicDelegate { get; set; }
    private Action<int, string> MethodDelegate { get; set; }

    private object[] Params { get; } = new object[] { 0, "Param2" };

    [GlobalSetup]
    public void Setup()
    {
        this.MethodInfo = typeof(Benchmark).GetMethod(nameof(TestMethod));
        this.MethodDynamicDelegate = Delegate.CreateDelegate(typeof(Action<int, string>), this, this.MethodInfo);
        this.MethodDelegate = this.TestMethod;
    }

    [Benchmark]
    public void MethodInfoInvoke()
    {
        this.MethodInfo.Invoke(this, this.Params);
    }

    [Benchmark]
    public void DelegateDynamicInvoke()
    {
        this.MethodDynamicDelegate.DynamicInvoke(this.Params);
    }

    [Benchmark]
    public void DelegateInvoke()
    {
        this.MethodDelegate.Invoke(0, "Param2");
    }

    public void TestMethod(int param1, string param2)
    {

    }
}
Lolop
  • 514
  • 2
  • 9
  • Thanks a lot ! :D Well.. i didnt expected this :o I would never have thought that the MethodInfo.Invoke is that faster and cheaper. – genaray Mar 31 '21 at 13:43
  • 1
    I was definitely surprised as well. If you look at [MethodInfo.Invoke (around like 700)](https://github.com/microsoft/referencesource/blob/master/mscorlib/system/reflection/methodinfo.cs) you'll see they are doing an unsafe call. I wont pretend to understand it, but I assume having all the meta data about the method allows them to skip a lot of checks. I couldn't find the `Delegate.DynamicInvoke` code to compare unfortunately. – Lolop Mar 31 '21 at 13:48