7

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よりもほぼ半分高速です。私はそれらが異なる目的のためであることを知っています(ループが実行される前に条件をチェックし、do-while少なくとも1回実行されます)。

私は、一般的なコンセンサスは、whileループが眉をひそめていることを知っています。

私の質問はなぜですか?PHPアプリケーションで使用されているforループの数を考えると、使用すべきではありませ。ループが実行される前に条件をチェックするifステートメントを使用しても、パフォーマンスは大幅に向上します。

私の現在受け入れられている答えは、コードの読みやすさが疑わしいということです。

10年編集: 10年前、就職の面接でこの質問をされました。私は、whileループが眉をひそめているという誤った認識でインタビューに入りました。これは、上司からの指示に従って、コードでwhileループが許可されていなかった以前の仕事から学びました。

The interview had gone well with management, then I was handed over to the lead programmer, he asked me what the fastest loop in PHP was, which I got incorrect and I did not get the job, this is why I asked the question on SO.

10 years of experience has taught me a lot.

  1. while loops are fine (its ludicrous to think I was taught otherwise)
  2. Micro-optimizations are truly evil (profile code, focus on bottle necks)
  3. in 10 years, I have never re-written a loop for speed. I have however rewritten the logic inside the loop which was always the true bottleneck.
  4. There is a lot of strongly held but largely incorrect opinions in the programming field. Stay the course, read up, experiment and question, be open to learning from better programmers and dont be afraid to be wrong.
4

3 に答える 3

18
  1. Micro optimizations are evil. They reduce readability for no measurable performance gain. Even if your application does have loops with millions of iterators (which I doubt) the difference is still negligible.
  2. The difference between while / do while is smaller than you say: http://codepad.viper-7.com/M8cgt9
  3. To understand why do while is marginally faster, look at the generated opcodes:

    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
    

    The do while loop only has one jump statement (JMPNZ), whereas the while loop needs two (JMPZ, JMP). The for loop needs three jump statements (JMPZNZ, JMP, JMP) and has generally more complex logic.

于 2011-11-10T14:53:19.050 に答える
1

If you want a fast loop you must unroll it or use a duff device.

You can also shortcut the for-loop (demo):

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

You can also shortcut the do-while loop (demo):

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

But the opcodes are the same.

And here is a modified version of the duff device from php.net:

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++;
}
?>

(This is a modified form of Duff's original device, because PHP doesn't understand the
original's egregious syntax.)

That's algorithmically equivalent to the common form:

<?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

If you're interested in that kind of thing, you may find PHPBench interesting.

My personal opinion is that you should use while, do and for loops where they are most legible. A 6% speed increase on an empty loop isn't significant enough if you're spending most of your time in the database.

于 2011-11-10T14:57:37.683 に答える