Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Func或Action是否比if else或switch case更快?_C# - Fatal编程技术网

C# Func或Action是否比if else或switch case更快?

C# Func或Action是否比if else或switch case更快?,c#,C#,我正在实现一个业务逻辑,其中比较和代码执行必须快速。假设我有一个能装1000箱的开关箱。诸如此类 public void DoWork(int num) { switch (num) { case 1: { function_1(); break; } cas

我正在实现一个业务逻辑,其中比较和代码执行必须快速。假设我有一个能装1000箱的开关箱。诸如此类

    public void DoWork(int num)
    {
        switch (num)
        {
            case 1:
                {
                    function_1();
                    break;
                }
            case 2:
                {
                    function_2();
                    break;
                }
            //.
            //.
            //.
            //.
            //.
            //UPTO 1000 CASES

            case 1000:
                {
                    function_1000();
                    break;
                }
        }
    }
现在,如果我用Func或Action来代替上面的代码,会不会更快??请参阅下面的代码

    //This array will be initialized previously
    Action[] actions = { new Action(function_1), new Action(function_2), /*....UPTO 1000....*/ new Action(function_1000) };
    public void DoWork(int num)
    {
        actions[num]();
    }
现在请告诉我哪一个会更快,为什么


感谢优化编译器已经知道如何使用计算分支来实现开关语句,其中控制变量是整数类型,案例是连续的。实际上,这意味着编译器已经在生成函数指针表了

交换机版本的一个优点是,如果调用的函数足够小,则可以内联,从而消除了比本地分支稍微昂贵的函数调用。内联还支持进一步优化。出于这个原因,编译器有时也会将间接调用转换为条件分支,这是一种称为设备化的优化

C没有提供这种优化,但是.NET JIT编译器可能会提供。这在很大程度上取决于x86、x64、ARM或安腾的体系结构和版本,而这一点您还没有提到。这并不是说,如果这些函数正在做一些非琐碎的事情,那么性能就会有很大的差异


底线与所有未充分描述的性能问题相同-您应该选择更易于维护的选项,除非您有分析器证据表明这是一个性能瓶颈。

虽然我同意带有1000个选项的switch语句对于生产代码几乎肯定不是一件好事,而且肯定很难维护,这个问题对于切换语句和动作代理的性能有好处

考虑一下下面的场景,我不止一次地遇到了这个问题

我在建一个班。 构造函数可以接收多个选项之一。 一旦我有了这个类的一个实例,我需要调用这个类上的某个方法1000万次。 在这种情况下,switch语句或委托操作/Func是否能更好地执行的问题变得很重要

具体地说,我可以在类方法中放入switch语句来处理各种场景,也可以在构造时分配适当的委托,这样我的类方法只需要调用预先分配的委托

现在,在构造过程中,我可能需要一个switch语句来分配委托,但我只需要这样做一次

那么问题是:运行switch语句1000万次,或者调用委托方法作为Action或Func 1000万次,会更快吗

这与老年退休金计划的问题并不完全相同,但我们中的许多人更可能遇到这样一个问题

许多人会马上说委托更快,因为一旦定义了它,它只是一个方法调用,比switch语句更快

…还是真的

正如在许多其他StackOverflow答案中提到的,switch对自身进行了一些优化。对于大量选项,它本质上是一个哈希集或字典。换句话说,非常快

但是方法调用的速度有多快?当然,这比没有方法调用要慢

我不够聪明,无法通过查看IL代码并通过目视检查推断一组指令是否比另一组指令快

所以我测试了它

在我进入我刚才描述的场景之前,我将首先展示OP场景的结果……但是开关中有50个选项,而不是1000个。复制和粘贴过多!:

我得到了一个与OP不同的结果。简言之,基于确切的场景,并确保我将苹果与苹果进行比较,我确定委托方法更快

基线测试-基线测试执行简单的整数加法操作1000万次。 OP的开关50-在这个测试中,我们调用了DoWork方法1000万次。DoWork方法包含一个带有50个选项的switch语句,每个选项调用另一个方法来执行简单的整数加法。正如我所说,我同意这种设计不是最优的。 OP的方法将委托作为操作-在本测试中,我们调用DoWork方法1000万次。DoWork方法从预先初始化的数组中调用特定的操作委托。代理执行了一个简单的整数加法。 结果:事实上,我预计在这种情况下,委托技术会更快,从191ms到258ms。我们在switch语句中还有一个额外的步骤,因为它要计算switch并仍然进行方法调用。但这就是问题的定义。而且,正如其他人所描述的,架构和内部优化可能意味着一台机器的性能与另一台不同

观点:结果有25%的差异。但让我们澄清一下。在很少的情况下,这种差异很重要。两种技术 在这种情况下,他们会尖叫得很快

现在,让我们回到我的场景

My Scenario 
+---------------------+------------+-----------+
|      TEST NAME      | ITERATIONS | Time (ms) |
+---------------------+------------+-----------+
| Switch (50 options) | 10 million |       192 |
| One Action Delegate | 10 million |        86 |
+---------------------+------------+-----------+
我的开关50-在这个测试中,我调用了一个方法DoWork,1000万次。内部DoWork是一个包含50个选项的开关语句。每个选项都做一个简单的整数内联加法。 我的单操作委托-在这个测试中,我选择了一个方法委托,并调用了1000万次。在委托内部执行简单的整数加法。 如果您忘记了,请重新阅读上面的内容,以记住我的场景是什么,以及我为什么比较这两个测试

结果:-同样,我希望单委托调用比使用内联代码计算switch语句更快。不过,我还是不确定。现在我是。这告诉我的是:

如果我的代码可能被调用数千次或数百万次,那么调用一个预定义的委托方法几乎比使用switch语句快3倍。 我再也不用担心这个问题了,因为这两种方法都快得惊人。 外卖:通过实际测量行为,我们现在可以看到一组可靠的数字,而不仅仅是猜测。也许在不同的机器上数字会有所不同,但我们仍然可以看到,对于已经非常快的东西来说,差异很小

最后,我将重复其他一些答案:


在考虑是否使用switch语句或方法委托时,您可能会遇到一些合法的情况,如果您只关心几毫秒,那么您只需要担心性能。否则,请使用任何可以保持代码干净和可维护的工具。

为什么不测试它?这似乎是过早的优化。您应该选择一个更具可读性的、基于观点的问题,并且只有当它确实是一个问题时才关心性能。这种类型的问题通常表明询问我们的人对您如何优化代码存在严重的、根本性的误解。提示:你认为编译器实际上是如何实现这样一个大的switch/case语句的?@Arnab有什么可能的原因?您想要的是易于理解、维护和调试的代码。您所关心的优化是算法上的,而不是实现上的
My Scenario 
+---------------------+------------+-----------+
|      TEST NAME      | ITERATIONS | Time (ms) |
+---------------------+------------+-----------+
| Switch (50 options) | 10 million |       192 |
| One Action Delegate | 10 million |        86 |
+---------------------+------------+-----------+