Perché è così lento?

PHPBench.com esegue script di benchmark rapidi su each pageload. Durante il test di foreach, quando lo carico, foreach richiede da 4 a 10 volte più tempo per eseguire rispetto al terzo esempio.

Perché la costruzione di un linguaggio nativo è apparentemente più lenta della logica?

Forse ha a che fare con il fatto che foreach funziona su una copia dell'arrays?

O forse ha a che fare con il fatto che, quando si esegue il ciclo con foreach, su each iterazione, il puntatore dell'arrays interno viene modificato, per puntare all'elemento successivo?

Citando la parte pertinente della pagina di manuale di foreach :

Nota: a less che l'arrays non faccia riferimento, foreach opera su una copia dell'arrays specificato e non sull'arrays stesso. foreach ha alcuni effetti collaterali sul puntatore dell'arrays.

Per quanto ne so, il terzo test a cui ti sei collegato non fa nessuna di queste due cose – il che significa che entrambi i test non fanno la stessa cosa – il che significa che non stai confrontando due modi di scrivere lo stesso codice .

(Direi anche che questo tipo di micro-ottimizzazione non ha alcuna importnza in una vera applicazione – ma immagino che tu lo sappia già, e solo per curiosità)

C'è anche una cosa che non sembra giusta in questo test: fa solo il test una volta ;; per un test "migliore", potrebbe essere utile testare tutti quelli più di una volta – con tempi nell'ordine di 100 microsecondi, non è necessario molto per fare un'enorme differenza.
(Considerando che il primo test varia tra il 300% e il 500% su alcuni aggiornamenti …)

Per coloro che non vogliono fare clic, ecco il primo test (ho ottenuto il 3xx%, il 443% e il 529%) :

 foreach($aHash as $key=>$val) { $aHash[$key] .= "a"; } 

E il terzo (100%) :

 $key = arrays_keys($aHash); $size = sizeOf($key); for ($i=0; $i<$size; $i++) { $aHash[$key[$i]] .= "a"; } 

Mi dispiace, ma il sito Web ha sbagliato. Ecco la mia sceneggiatura che mostra che i due sono quasi la stessa velocità, e infatti, foreach è più veloce!

 <?php function start(){ global $aHash; // Initial Configuration $i = 0; $tmp = ''; while($i < 10000) { $tmp .= 'a'; ++$i; } $aHash = arrays_fill(100000000000000000000000, 100, $tmp); unset($i, $tmp); reset($aHash); } /* The Test */ $t = microtime(true); for($x = 0;$x<500;$x++){ start(); $key = arrays_keys($aHash); $size = sizeOf($key); for ($i=0; $i<$size; $i++) $aHash[$key[$i]] .= "a"; } print (microtime(true) - $t); print ('<br/>'); $t = microtime(true); for($x = 0;$x<500;$x++){ start(); foreach($aHash as $key=>$val) $aHash[$key] .= "a"; } print (microtime(true) - $t); ?> 

Se guardi il codice sorgente dei test: http://www.phpbench.com/source/test2/1/ e http://www.phpbench.com/source/test2/3/ , puoi vedere che $ aHash non viene ripopolato ai dati iniziali dopo each iterazione. Viene creato una volta all'inizio, quindi each test viene eseguito X volte. In questo senso, stai lavorando con un $ aHash sempre crescente per each iterazione … in psuedocode:

 iteration 1: $aHash[10000000000000]=='aaaaaa....10000 times...a'; iteration 2: $aHash[10000000000000]=='aaaaaa....10001 times...a'; iteration 2: $aHash[10000000000000]=='aaaaaa....10002 times...a'; 

Nel tempo, i dati per tutti i test si stanno ingrandendo per each iterazione, quindi ovviamente con l'iterazione 100, il metodo arrays_keys è più veloce perché avrà sempre le stesse chiavi , where il ciclo foreach deve fare i conti con un numero sempre crescente set di dati e memorizzare i valori negli arrays!

Se esegui il mio codice fornito sopra sul tuo server, vedrai chiaramente che foreach è più veloce E più pulito E più chiaro.

Se l'autore del sito voleva che il suo test facesse quello che fa, allora non è certamente chiaro, e in caso contrario, è un test non valido.

I risultati del benchmark per tali micro misurazioni, provenienti da un server web attivo e in tensione, sobject a quantità estreme di carico variabile e altre influenze, dovrebbero essere ignorati. Questo non è un ambiente di riferimento in