7

我用一些简单的东西分析了 forwhiledo-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. 在编程领域有很多强烈但基本上不正确的观点。坚持到底,阅读、实验和提问,向更好的程序员学习敞开心扉,不要害怕犯错。
4

3 回答 3

18
  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)并且通常具有更复杂的逻辑。

于 2011-11-10T14:53:19.050 回答
1

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

您还可以缩短 for 循环(演示):

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
于 2011-11-10T14:45:24.987 回答
1

如果您对这类事情感兴趣,您可能会发现PHPBench很有趣。

我个人的看法是,你应该在最易读的地方使用 while、do 和 for 循环。如果您将大部分时间都花在数据库中,那么在空循环上提高 6% 的速度还不够显着。

于 2011-11-10T14:57:37.683 回答