-3

Possible Duplicate:
Is it faster to count down than it is to count up?

Hello I have an interesting question. Which version of the cycle will be more effective?

for ($i=0;$i<10000;$i++)
    echo $i  . "\n";

OR

for ($i=10000;$i--;) 
    echo $i  . "\n";

I think the second version is more efficient with respect to time and memory consumption.

Thank you.

Community
  • 1
  • 1
glebus
  • 197
  • 1
  • 1
  • 11

5 Answers5

3

The first loop is more efficient at printing numbers 0..9999.

The second takes the prize for numbers 9999...0.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
1

It makes bu**er all difference. I haven't done the disassably but I suspect that there is probably 1 opcode difference and since the PHP interpreter runs @ ~20M opcodes per second, you are looking at far less than one microsecond difference.

Just focus on clarity. Going backwards down a loop is being "clever" not smart, and the trouble with being clever is that you make mistakes.

What the disassembly tells us

Here are the two side-by side:

         $i=0; $i<10000; $i++                              $i=10000; $i--;   
line     # *  op   ext return  operands          line     # *  op   ext  return  operands
  0  >   EXT_STMT                                  0  >   EXT_STMT                
  1      ASSIGN                  !0, 0             1      ASSIGN                  !0, 10000
  2  >   IS_SMALLER      ~1      !0, 10000         2  >   POST_DEC        ~1      !0
  3      EXT_STMT                                  3      EXT_STMT                
  4    > JMPZNZ     8            ~1, ->11          4    > JMPZNZ     6            ~1, ->9
  5  >   POST_INC        ~2      !0                 
  6      FREE                    ~2                 
  7    > JMP                     ->2               5  > > JMP                     ->2
  8  >   CONCAT          ~3      !0, '%0A'         6  >   CONCAT          ~2      !0, '%0A'
  9      ECHO                    ~3                7      ECHO                    ~2
 10    > JMP                     ->5               8    > JMP                     ->5

as I said one or two opcodes diffferent.

Benchmarking this

This types type of benchmark shown in other answers are weak. Let me explain why in a nutshell: You need to benchmark the right thing and you need to take enough samples to be statistically significant. Here is my little test:

<?php
$stat = array ();
for( $j=0; $j<1001; $j++ ) {
    $s1 = microtime( TRUE );
    for( $i=0; $i<10000; $i++ ) $a = 0;
    $s2 = microtime( TRUE );
    for ( $i=10000; $i--; ) $a = 0;
    $s3 = microtime( TRUE );
    if( $j>0 ) $stat[]=array($s2-$s1, $s3-$s2,$s3-$s2-$s2+$s1);
}    
foreach ($stat as $s) echo "{$s[0]}\t{$s[1]}\n";

This collect 100 samples of a 10K loop as about replacing the echo by a trivial statement. I loaded the O/P into a spread sheet and got a delta mean of 0.035 µSec with a std dev of 0.017 µSec inner loop. However if I replace the $a assignment by echo $1, this moves to 0.131 µSec average delta and a std dev of 0.185 µSec. This because the looptime is now 4.12 µSec.

Guys, OK we all may have come across stats which show post decrement is slightly better than predecrement, but it makes no real-world difference!!!!!

Community
  • 1
  • 1
TerryE
  • 10,724
  • 5
  • 26
  • 48
0

The second version is slightly faster. However, this this really of very limited importance in PHP.

Have you noticed, however, that the two versions do not produce the same output? Now, this is very important.

linepogl
  • 9,147
  • 4
  • 34
  • 45
0

I did a quick benchmark:

<?php
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$start = $time;

for ($count = 0; $count < 1000; $count++) {
    for ($i=0;$i<10000;$i++);
}

$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$end = $time;
$diff = ($end - $start);
echo "Version 1 time: $diff seconds.";

$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$start = $time;

for ($count = 0; $count < 1000; $count++) {
    for ($i=10000;$i--;);
}

$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$end = $time;
$diff = ($end - $start);
echo "Version 2 time: $diff seconds.";

?>

Test 1:
Version 1 time: 0.42717981338501 seconds.
Version 2 time: 0.46911406517029 seconds.

Test 2:
Version 1 time: 0.44191193580627 seconds.
Version 2 time: 0.46684908866882 seconds.

Test 3:
Version 1 time: 0.43247008323669 seconds.
Version 2 time: 0.46166205406189 seconds.

Edit

I did the benchmark again and now the second version is faster:

Test 1:
Version 1 time: 0.43037080764771 seconds.
Version 2 time: 0.29532289505005 seconds.

Test 2:
Version 1 time: 0.42874693870544 seconds.
Version 2 time: 0.29753398895264 seconds.

Test 3:
Version 1 time: 0.44300508499146 seconds.
Version 2 time: 0.2880539894104 seconds.

Actually I posted this answer because the results I'd got the first time, where not what I expected. but now the results are what they should be.

The reason as others explained is that comparing with zero executes faster.

fardjad
  • 20,031
  • 6
  • 53
  • 68
0

Wicked!.. The second is really about two times faster! That is noticable even on just 10000 cycles, like in your example. I did this test:

$time = microtime( True);
for ($i=0;$i<10000;$i++) $b = $i;
$lapse1 = microtime( true) - $time;
echo "Time one: ".$lapse1.PHP_EOL;

$time = microtime( True);
for ($i=10000;$i--;) $b = $i;
$lapse2 = microtime( true) - $time;
echo "Time two: ".$lapse2.PHP_EOL;

This gave me:

Time one: 0.0010528564453125
Time two: 0.00066709518432617

Have no idea, why, though.

Serge
  • 1,531
  • 2
  • 21
  • 44