执行时间:直接vs反思vs委托

时间:2019-05-13 17:23:06

标签: c# optimization reflection delegates execution-time

在研究反思和代表时,我偶然发现了这个Jon Skeet's post的第一个示例。

尽管反射以缓慢而臭名昭著,尤其是对于重复调用,但我真的不明白如何将反射方法“包装”到Delegate中可以避免其高计算成本,就像在第一个示例中建议的那样:

MethodInfo method = typeof(string).GetMethod("IndexOf", new Type[] { typeof(char) });

Func<char, int> converted = (Func<char, int>)
            Delegate.CreateDelegate(typeof(Func<char, int>), str, method);

因此,基于该示例,我为自己建立了一个简短的比较测试。我正在尝试比较对字符串IndexOf方法的不同调用:A)直接; B)使用反射; C)使用委托。

/*
Based on 
https://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/
*/
public class Test
{
    public static void Main()
    {
        // Testing the performance of different calls to string method "IndexOf"

        string str = "Hello World";

        Stopwatch s = new Stopwatch();
        float elapsed = 0;
        int iterations = 10000000;

        //---------
        // A) Direct
        //---------
        for (int i = 0; i < iterations; i++)
        {
            // Average to reduce noise error
            s.Start();
            str.IndexOf('H');
            s.Stop();
            elapsed += s.Elapsed.Ticks;
            s.Reset();
        }

        Console.WriteLine("A) Direct: " + (elapsed / iterations).ToString());

        elapsed = 0;

        //---------
        // B) Reflection
        //---------

        MethodInfo method = typeof(string).GetMethod("IndexOf", new Type[] { typeof(char) });

        for (int i = 0; i < iterations; i++)
        {
            // Average to reduce noise error
            s.Start();
            method.Invoke(str, new object[] { 'H' });
            s.Stop();
            elapsed += s.Elapsed.Ticks;
            s.Reset();
        }

        Console.WriteLine("B) Reflection: " + (elapsed / iterations).ToString());

        elapsed = 0;

        //---------
        // C) Delegate
        //---------

        Func<char, int> converted = (Func<char, int>)
            Delegate.CreateDelegate(typeof(Func<char, int>), str, method);

        for (int i = 0; i < iterations; i++)
        {
            // Average to reduce noise error
            s.Start();
            converted('H');
            s.Stop();
            elapsed += s.Elapsed.Ticks;
            s.Reset();
        }

        Console.WriteLine("C) Delegate: " + (elapsed / iterations).ToString());
    }
}

在我的计算机上,典型运行将返回以下内容:

A) Direct: 0.2621305
B) Reflection: 2.571738
C) Delegate: 0.2736629

问题

1)为此目的,我的测试/测量策略是否正确?

2)我想深入解释为什么使用委托形式C)比B)更快。幕后发生了什么?

附加说明

在回答特别是问题2)时,请考虑我在反思和代表方面都是初学者。请尝试详尽无遗,但可以理解。

我已经围绕其他围绕这些主题的Stackoverflow问题进行了研究,但无法解决:Performance of reflection method call vs delegate callWhat is the "cost" of .NET reflection?; How costly is .NET reflection?

0 个答案:

没有答案