【问题标题】:What is faster: many ifs, or else if?什么更快:许多 if 或 else if?
【发布时间】:2010-12-20 05:55:18
【问题描述】:

我正在遍历一个数组并按值将其排序为一周中的几天。

为了做到这一点,我使用了许多 if 语句。如果我使用多个ifs,而不是一组else if 语句,它对处理速度有什么影响吗?

【问题讨论】:

  • 我不知道处理速度,但是如果你有这么多的 if 块,也许你应该考虑使用 switch 语句。特别是对于像一周中的几天这样的事情。
  • 从多个 if 语句更改为一个 if-elseif 语句时,功能发生了巨大变化。想想你的代码到底做了什么。

标签: php micro-optimization


【解决方案1】:

你可以看看phpbench

但老实说,如果你想在这个级别进行优化,你可能想学习 php 以外的其他东西。

【讨论】:

    【解决方案2】:

    if 块返回从而完成该方法时,这个问题特别有趣。它也直接适用于 Java 中比较器的工作方式。

    因此,我已将每种方法(如下)运行了 250.000.000 次,结果如下:

    two values   if/else    - 6.43 millis
    three values if/else/if - 8.66 millis
    three values if/if      - 9.01 millis
    

    虽然最坏情况比最好情况花费的时间长 1.4 倍,但请注意,这是将这些方法中的每一种迭代 2.5 亿次的总和。假设人类感知延迟需要 100 毫秒,并且最差/更好的差异是 2.58 毫秒,这意味着您需要近一万亿(1000 * 10 亿)次迭代才能感知不同方法之间的差异。

    总结一下: 使用if-else 这是其中最快的选项也是更易读且不易出错的选项之一。

    // methods used to measure difference between if and if/else
    
    /** equality is not important **/
    private static int comparatorOfIfElse(int a, int b) {
        if(a < b) return -1;
        else return  1;
    }
    
    /** equality is taken into account using if/else **/
    private static int comparatorOfIfElseIf(int a, int b) {
        if(a < b) return -1;
        else if(a > b) return  1;
        return 0;
    }
    
    /** equality is taken into account using only if **/
    private static int comparatorOfIf(int a, int b) {
        if(a < b) return -1;
        if(a > b) return  1;
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      如果连续的 if() 和 if() 之间存在真正的区别,那么我做了一个基准测试,然后是一些 elseif()

      我放了一个大字符串,用这两种方法每次(x100 000)做了大约 20 个 strpos(),它显示了这个结果:

      Try 1 : 0.5094 (including elseif)
      Try 2 : 0.6700 (including only if)
      

      毫无疑问。我已经知道连续 elseif() 更快,即使中间有 return ;在答案中加入一些统计数据仍然很好。

      【讨论】:

        【解决方案4】:

        我会再次投票选择 switch() 语句。

        【讨论】:

        • if else 链切换的技术原因是什么?还是只是个人喜好?
        • 这个问题(和答案)已有十多年的历史了,但是是的,我倾向于使用switch,其中有有限数量的选项(就像一周中的几天一样);并使用if 进行基于布尔表达式的分支条件逻辑(“如果此条件为真,则执行此代码块……”)。
        【解决方案5】:

        else if 在您比较的意义上会更快,直到您遇到解析为 true 的条件,然后您跳过 ifs 的其余部分。

        还可以考虑按频率降序对比较进行重新排序。

        并根据您要比较的对象的数据类型使用switch 语句。

        但是,正如 duffymo 所建议的那样,此时您将进行微优化。如果您没有首先为作业选择正确的排序算法,性能提升将永远不会那么显着。

        【讨论】:

          【解决方案6】:

          使用多个 if 语句或一个 if-elseif-elseif... 的决定不应依赖于性能,因为该决定涉及大量程序流程。

          我怀疑您是否可以在不丢失功能的情况下从许多 if 语句切换到大型 if-elseif。

          这是一个设计问题,而不是性能问题。

          【讨论】:

            【解决方案7】:

            我怀疑像这样的微优化会在您的代码中产生可衡量的差异。

            您的排序算法更有可能是性能问题的根源。您选择哪种排序算法很关键,“ifs”与“else if”并不多。

            更新:

            其他人关于“else if”是一个更好的选择的观点,由于其提前退出和排他的逻辑特性,表明在这种情况下它应该优于“if”。

            但是关于算法选择的观点仍然存在——除非你的数据集非常小。

            显然 O(log n) 会比 O(n^2) 好,但数据集的大小也很重要。如果您只有几个元素,您可能不会注意到差异。在这种情况下,以最简洁、最易读、最容易理解的方式编写一个低效的方法可能是你最好的选择。

            【讨论】:

            • 大多数排序算法使用嵌套循环或递归以及大量比较来对给定集合进行排序。根据他在代码的这个关键部分进行的比较次数,提前退出和跳过不必要的比较可能会显着提高性能。
            • if-else 是否也有助于提高可读性,以及给编译器一个体面的提示?
            【解决方案8】:

            一般来说,“else if”样式会更快,因为在一系列 if 中,每个条件都被一个接一个地检查;在“else if”链中,一旦匹配了一个条件,其余的就会被绕过。

            最快的将是表调度,这是当 switch 语句中有足够的 case 时被优化的内容(如果 switch 中的 case 很少,它会被转换为一系列 if-else 检查生成的机器代码)。

            【讨论】:

              【解决方案9】:

              如果值是整数,您可以通过使用表查找来实现优化。例如。假设您有 256 个值以某种方式映射到 7 天,您可以设置一个包含 256 个单元格的数组,每个单元格包含您想要的星期几。然后代替:

              
              if ( value == 0 ) {
                dayofweek = 1;
              } else if ( value == 1 ) {
                dayofweek = 2;
              } else if ( value == 2 ) {
                dayofweek = 3;
              } else if ...
              

              ..你可以有..

              
              dayofweek = lookuparray[value];
              

              当然,如果你使用这种技术,那么你应该先检查值的界限。

              【讨论】:

                【解决方案10】:

                是的,使用 else if,考虑以下代码:

                if(predicateA){
                  //do Stuff
                }
                if(predicateB){
                  // do more stuff
                }
                

                if(predicateA){
                  //
                }
                else if(predicateB){
                  //
                }
                

                在第二种情况下,如果 predicateA 为真,则不需要计算 predicateB(以及任何其他谓词)(因此整个代码将执行得更快),而在第一个示例中,如果 predicateA 为真,则 predicateB 仍将始终被评估,如果 predicateA 和 predicateB 不互斥,你也可能会得到一些意想不到的惊喜。

                【讨论】:

                • 实际看到性能差异需要大量条件,但是 +1 好像无论如何都是正确的方法。
                • 实际上,您的示例是错误的,因为如果 PredicateA 和 PredicateB 都可以发生,它们将不会做同样的事情。您只会执行第一个并退出。而第一个代码将同时执行。
                【解决方案11】:

                老实说,我认为你在性能方面采用哪种方式并不重要,我怀疑你会看到任何不同。我建议使用不是性能增强的 switch 语句,只是在语法上更好:

                switch ($day) 
                {
                    case "Monday":
                        // do something with Monday
                        break;
                    case "Tuesday":
                        // do something with Tuesday
                        break;
                    case "Wednesday":
                        // do something with Wednesday
                        break;
                }
                

                【讨论】:

                • 一个开关绝对是对许多 if 的性能提升!
                猜你喜欢
                • 1970-01-01
                • 2012-06-02
                • 2010-10-19
                • 1970-01-01
                • 2017-05-12
                • 2018-09-19
                • 1970-01-01
                • 2018-07-10
                • 1970-01-01
                相关资源
                最近更新 更多