Can Delegate.DynamicInvoke be avoided in this generic code?

前端 未结 3 1008
醉话见心
醉话见心 2021-02-05 22:27

This question is partly about delegates, and partly about generics.

Given the simplified code:

internal sealed class TypeDispatchProcessor
{
    private          


        
3条回答
  •  醉梦人生
    2021-02-05 23:07

    So I did some measurements on this.

    var delegates = new List();
    var actions = new List>();
    
    const int dataCount = 100;
    const int loopCount = 10000;
    
    for (int i = 0; i < dataCount; i++)
    {
        Action a = d => { };
        delegates.Add(a);
        actions.Add(o => a((int)o));
    }
    
    var sw = Stopwatch.StartNew();
    for (int i = 0; i < loopCount; i++)
    {
        foreach (var action in actions)
            action(i);
    }
    Console.Out.WriteLine("{0:#,##0} Action calls in {1:#,##0.###} ms",
        loopCount * dataCount, sw.Elapsed.TotalMilliseconds);
    
    sw = Stopwatch.StartNew();
    for (int i = 0; i < loopCount; i++)
    {
        foreach (var del in delegates)
            del.DynamicInvoke(i);
    }
    Console.Out.WriteLine("{0:#,##0} DynamicInvoke calls in {1:#,##0.###} ms",
        loopCount * dataCount, sw.Elapsed.TotalMilliseconds);
    
    
    

    I created a number of items to indirectly invoke to avoid any kind of optimisation the JIT might perform.

    The results are quite compelling!

    1,000,000 Action calls in 47.172 ms
    1,000,000 Delegate.DynamicInvoke calls in 12,035.943 ms
    
    1,000,000 Action calls in 44.686 ms
    1,000,000 Delegate.DynamicInvoke calls in 12,318.846 ms

    So, in this case, substituting the call to DynamicInvoke for an extra indirect call and a cast was approximately 270 times faster. All in a day's work.

    提交回复
    热议问题