Do-while是php中最快的循环


do-while is the fastest loop in php?

我用一些简单的东西来描述whiledo-while循环:

while ($var < 1000000) {
  ++$var;
}
do {
  ++$var;
} while ($var < 1000000);
for ($var = 0; $var < 1000000; ++$var) {
  //do nothing
}

通过比较循环前后的microtime()。

do-while循环绝对是最快的循环。do-while实际上比while快近一半。我知道它们有不同的用途(while在循环执行前检查条件,do-while至少执行一次)。

我知道一般的共识是不赞成while循环,而do-while循环更是如此。

我的问题是为什么?考虑到PHP应用程序中使用了多少for循环,不应该更多地使用do-while吗?即使使用if语句在循环执行之前检查条件,性能提升也是相当可观的。

我目前接受的答案是代码的易读性是可疑的。

10年编辑:10年前,我在一次面试中被问到这个问题。我带着错误的想法去面试,认为while循环是不受欢迎的。我从以前的工作中学到了这一点,根据上级的指示,while循环在代码中是不允许的。

面试进行得很顺利,然后我被交给了首席程序员,他问我PHP中最快的循环是什么,我答错了,所以我没有得到这份工作,这就是为什么我问了SO这个问题。

10年的经历教会了我很多。

  1. while循环很好(认为我被教导不然是可笑的)
  2. 微优化是真正的邪恶(配置文件代码,关注瓶颈)
  3. 10年来,我从来没有为了速度重写过一个循环。然而,我重写了循环内部的逻辑,这一直是真正的瓶颈。
  4. 在编程领域有很多强烈的,但很大程度上是错误的观点。坚持到底,阅读,实验和提问,向更好的程序员学习,不要害怕犯错。
  1. 微优化是邪恶的 。它们降低了的可读性,而没有可测量的性能增益。即使你的应用程序有数百万个迭代器的循环(我怀疑这一点),差异仍然可以忽略不计。
  2. while/do while的差异比你说的要小:http://codepad.viper-7.com/M8cgt9
  3. 要理解为什么do while稍微快一点,请查看生成的操作码:

    line     # *  op                           fetch          ext  return  operands
    ---------------------------------------------------------------------------------
    # while loop
       3     0  >   ASSIGN                                                   !0, 0
       4     1  >   IS_SMALLER                                       ~1      !0, 1000000
             2    > JMPZ                                                     ~1, ->5
             3  >   PRE_INC                                                  !0
             4    > JMP                                                      ->1
             5  > > RETURN                                                   1
    # do while loop
       3     0  >   ASSIGN                                                   !0, 0
       4     1  >   PRE_INC                                                  !0
             2      IS_SMALLER                                       ~2      !0, 1000000
             3    > JMPNZ                                                    ~2, ->1
       4        > > RETURN                                                   1
    # for loop
       3     0  >   ASSIGN                                                   !0, 0
             1  >   IS_SMALLER                                       ~1      !0, 1000000
             2    > JMPZNZ                                        5          ~1, ->6
             3  >   PRE_INC                                                  !0
             4    > JMP                                                      ->1
             5  > > JMP                                                      ->3
             6  > > RETURN                                                   1
    

    do while循环只有一个跳转语句(JMPNZ),而while循环需要两个(JMPZ, JMP)。for循环需要三个跳转语句(JMPZNZ, JMP, JMP),通常具有更复杂的逻辑。

如果你对这类东西感兴趣,你可能会发现PHPBench很有趣。

我个人的意见是,你应该使用while, do和for循环,它们是最清晰的。如果您将大部分时间花在数据库中,那么空循环上6%的速度提升并不足够显著。

如果你想要快速循环,你必须展开它或使用duff设备。

你也可以将for循环(demo)快捷化:

for ($var = 0; ++$var < 10; ) {
   // do nothing
}

你也可以快捷地执行do-while循环(demo):

$var=0;
do {
    echo "Hello";
} while (++$var < 10);

但是操作码是一样的

下面是来自php.net的duff设备的修改版本:

If you're already using the fastest algorithms you can find (on the order of O(1),      
O(n), or O(n log n)), and you're still worried about loop speed, unroll your loops  
using e.g., Duff's Device:
<?php
$n = $ITERATIONS % 8;
while ($n--) $val++;
$n = (int)($ITERATIONS / 8);
while ($n--) {
  $val++;
  $val++;
  $val++;
  $val++;
  $val++;
  $val++;
  $val++;
  $val++;
}
?>

(这是Duff原始设备的修改形式,因为PHP不理解
)

在算法上等价于一般形式:

<?php
 for ($i = 0; $i < $ITERATIONS; $i++) {
   $val++;
}
?>
$val++ can be whatever operation you need to perform ITERATIONS number of times.
On my box, with no users, average run time across 100 samples with ITERATIONS =     
10000000 (10 million) is:
Duff version:       7.9857 s
Obvious version: 27.608 s