2011-11-10 19 views
6

ho profilato per, mentre e do-while loop con qualcosa di semplice:do-while è il loop più veloce in php?

while ($var < 1000000) { 
    ++$var; 
} 

do { 
    ++$var; 
} while ($var < 1000000); 

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

confrontando microtime() prima e dopo i cicli.

Il ciclo di do-while è di gran lunga il ciclo più veloce. do-mentre è in realtà più veloce di mentre di quasi la metà. So che sono per scopi diversi (mentre controlla la condizione prima che il ciclo venga eseguito e do-mentre eseguito almeno una volta).

So che il consenso generale è che mentre i loop sono disapprovati e lo fanno - mentre ancora di più.

La mia domanda è perché? Considerando quanti loop for sono usati nelle applicazioni PHP, non dovrebbe essere usato più do-mentre? Anche con un se l'istruzione verifica una condizione prima dell'esecuzione del ciclo, l'aumento delle prestazioni è considerevole.

La mia risposta attualmente accettata è che la leggibilità del codice è il sospetto.

+0

È possibile pubblicare i risultati del benchmarking? – bot403

+1

Non ho mai visto questo consenso sul fatto che i loop siano cattivi. Sono uno strumento nel toolkit PHP, come qualsiasi altro. –

+0

Chi si acciglia mentre si avvicina? Usare solo la metà del tempo sembra molto, ma dovresti misurare il tempo reale che stai salvando. Stai salvando la metà del nulla. – martinstoeckli

risposta

15
  1. Le micro ottimizzazioni sono malvagie. Riducono la leggibilità per no guadagno misurabile di prestazioni. Anche se la tua applicazione ha loop con milioni di iteratori (che dubito) la differenza è ancora trascurabile.
  2. La differenza tra while/do while è più piccolo di lei dice: http://codepad.viper-7.com/M8cgt9
  3. Per comprendere il motivo per cui do while è marginalmente più veloce, guardare i codici operativi generati:

    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 
    

    Il ciclo do while ha solo un'istruzione di salto (JMPNZ), mentre il ciclo while ne richiede due (JMPZ, JMP). Il ciclo for richiede tre istruzioni di salto (JMPZNZ, JMP, JMP) e ha una logica generalmente più complessa.

+0

Io non la penso così. Se è pagato per questo. Se gli piace. Quando ha un milione di iteratori, ha senso. – Bytemain

+0

@Jitamaro anche se ci sono milioni di iterazioni la differenza tra while/do-while/for è quasi sempre trascurabile rispetto al tempo impiegato a fare cose all'interno del ciclo. – Marcus

+0

Il ciclo è trascurabile, la velocità dell'algoritmo, la memoria presa è più importante – andho

1

Se si desidera un ciclo veloce, è necessario srotolarlo o utilizzare un dispositivo duff.

È inoltre possibile scorciatoia per-loop (demo):

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

È anche possibile scorciatoia del ciclo do-while (demo):

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

Ma i codici operativi sono gli stessi.

E qui è una versione modificata del dispositivo duff da 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++; 
} 
?> 

(Questa è una forma modificata di dispositivo originale di Duff, perché PHP non capisce la sintassi egregio il
dell'originale.)

Questo è algoritmicamente equivalente alla forma comune:

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

Se sei interessato a questo genere di cose, potresti trovare interessante PHPBench.

La mia opinione personale è che si dovrebbe usare mentre, fare e per cicli in cui sono più leggibili. Un aumento della velocità del 6% su un ciclo vuoto non è abbastanza significativo se passi la maggior parte del tuo tempo nel database.

Problemi correlati