L'instruction foreach
est plus rapide que l'instruction for
, au moins avec PHP 5.3.2.
Pour arriver à cette conclusion, j'ai utilisé les deux scripts, l'un pour tester l'instruction for
et l'autre bien évidement pour tester l'instruction foreach
.
Voici celui utilisé pour tester for
, avec en commentaire la modification à effectuer pour tester foreach
:
<?php
//remplacé par "foreach ($array as $value)" pour la version foreach.
for ($range = 100000; $range <= 1000000; $range += 10000)
{
$array = range(1, $range);
$start = microtime(true);
$memory = memory_get_usage();
ob_start();
for ($i = 0, $end = sizeof($array); $i < $end; $i++)
{
//remplacé par "echo $value;" pour la version foreach
echo $array[$i];
}
ob_end_clean();
$duration = microtime(true) - $start;
$memory = memory_get_usage() - $memory;
echo $range . ';' . $duration . ';' . $memory . ';' . memory_get_peak_usage() . "\n";
unset($array);
}
?>
Donc comme je le disais, foreach
est plus rapide que for
... de... attention... roulement de tambour... 3% en moyenne.
Je ne parlerai même pas du différentiel en terme d'occupation mémoire, tellement il frise le ridicule.
Tout cela pour dire que ce genre de débat ressemble furieusement à celui opposant print
à echo
, et que j'ai furieusement l'impression que certaines personnes ont un amour particulier pour les drosophiles.
D'autant qu'en plus, le débat n'a même pas lieu d'être, notament depuis l’avènement de PHP 5.
L'instruction foreach
a en effet ceci de pratique depuis cette époque qu'elle est capable de s'interfacer directement avec un objet de la classe iterator
ou qui implémente l'interface iteratorAggregate
.
C'est d'ailleurs tellement pratique que je n'utilise pratiquement plus que des itérateurs dans mon code, au dépend de l'instruction for
, qui ne permet aucunement cela.
Les deux instructions sont donc fondamentalement différentes dans leur philosophie, for
étant une instruction simple
alors que foreach
est magique
et permet de parcourir des objets, éventuellement multi-dimensionnels et/ou récurisifs.
Enfin, si l'on se cantonne strictement au parcours de tableaux, for
était plus pratique que foreach
en PHP 4 car il permettait la modification des valeurs du tableau, ce que ne permettait pas foreach
, qui travaillait à l'époque sur une copie du tableau qu'il recevait en argument.
Or, PHP 5 a éliminé cet inconvénient en permettant l'utilisation de l'opérateur &
dans une instruction foreach
.
Pour une manipulation de tableaux à une dimension, for
et foreach
sont donc devenues strictement équivalentes depuis PHP 5, fonctionnellement parlant.
Je suis donc surpris que des référents techniques
se posent ce type de questions existentielles et encore plus qu'ils acceptent de prendre part à ce genre de débat stérile.
A mon sens, ils devraient préconiser une solution en fonction des avantages fonctionnels qu'elle apporte dans le contexte d’exécution, et non en terme de performance, surtout dans ce cadre.
En effet, ce paramètre est très peu pertinent dans le cas d'instructions de bas niveau, et il est de plus susceptible d'évoluer, dans un sens ou dans l'autre, en fonction des versions du langage.
10 réactions
1 De Mouf - 09/06/2010, 15:10
Amen pour la conclusion!
Et je ne parlerai pas du débat fondamental entre les utilisateurs de simple et de double quotes.
Si seulement les "référents techniques" se focalisaient plus sur les vraies bonnes pratiques (architecture, modèle de données, création d'index...) plutôt que sur l'indentation et comment faire une boucle!
2 De Un lecteur - 09/06/2010, 15:25
Hors contexte, la question ne manque pas forcément de pertinence.
Dans l'absolu on peut vouloir rechercher la performance optimale à tout prix pour un besoin particulier. Cependant, cette recherche de performance me semble contradictoire avec les cas d'utilisation usuels de php (web essentiellement, scripting parfois).
Maintenant je suis d'accord sur le fait que vu l'écart de performance, c'est surtout les avantages fonctionnels qui doivent primer. Donc +1 pour le foreach
HS: je prends beaucoup de plaisir à vous lire mais je trouve qu'il y a vraiment beaucoup de fautes dans le texte et c'est bien dommage au regard de la pertinence de votre blog. Désolé, ça me tient à coeur :p
3 De metagoto - 09/06/2010, 16:13
Je n'ai pas testé ton code.
Je sais par contre qu'il faut faire un pre inc au lieu d'un post inc (dans le for et en général dès qu'on le peut) car php ne sait pas optimiser ça. Chaque post inc entraine une var temporaire qui est détruite dans la foulée.
Pour des ranges plus faibles que les tiens, du genre 1..1000, alors le for peut l'emporter si les opérations ne sont pas trop complexes. Après c'est un match entre la VM vs. ce qui peut être codé "en dur" en C. C'est d'ailleurs une des raisons pour privilégier les fonctions "toutes faites" de php (du genre foreach) plutôt que de se tapper le boulot manuellement.
Dans un code qui devrait vraiment être optimisé à mort, alors des micro benches pour choisir foreach ou for (ou goto;) me sembleraient nécessaires. On ne peut pas décréter que foreach est toujours plus performant que for.
Un petit output avec bytekit ou vld n'aurait pas été de trop
4 De Greg - 09/06/2010, 16:28
Ce site est toujours utile pour ce genre de débat :
http://phpbench.com/
5 De desfrenes - 09/06/2010, 16:58
"There should be one
and preferably only oneobvious way to do it.": http://docs.python.org/tutorial/con...
Sinon le débat est d'autant plus "savoureux" sachant que la plupart des débutants comptent la taille du tableau à chaque itération de la boucle for
6 De mageekguy - 09/06/2010, 17:41
@Un lecteur : Je vais faire un effort pour l'orthographe.
@metagoto : Utiliser bytekit ou vld pour un débat de cet importance, c'est utiliser une massue pour écraser une mouche, tellement le débat me semble à côté de la plaque,
Et si une application doit être tellement rapide qu'elle nécessite un tel niveau d'optimisation, il ne faut pas l'écrire en PHP, mais en C/C++, bref, un langage compilé efficace (on parle dans le cas présent de 3% d'écart sur... 0.6 seconde pour un tableau d'un million d'éléments sur un ordinateur portable de 2005).
Et j'ai bien conscience que l'efficacité peut varier en fonction de la taille du tableau, c'est pourquoi ce paramêtre est une variable dans mon script.
7 De CrazyCat - 09/06/2010, 17:43
Très bon post permettant de démontrer l'inutilité de certains débats malheureusement trop fréquents.
Par contre, mauvais placement du premier commentaire qui devrait se trouver au niveau du "for ($i = 0, $end = sizeof($array); $i < $end; $i++)", il y en a qui vont se planter :D
8 De desfrenes - 09/06/2010, 21:41
"je ne parlerai pas du débat fondamental entre les utilisateurs de simple et de double quotes"
Ouais... enfin c'est quand même pas qu'une question de performance là !
mickael@enclume:~$ cat quotes.php
<?php
$mouf = 'Mouf';
echo '\n Hello $mouf \n';
echo "\n Hello $mouf \n";
mickael@enclume:~$ php quotes.php
\n Hello $mouf \n
9 De mageekguy - 10/06/2010, 09:09
@desfrenes : Il y a bien un débat sur ce sujet... malheureusement.
10 De ashgenesis - 10/06/2010, 11:12
@desfrenes : Le débat se situe plus dans l'utilisation des doubles quotes lorsque nous n'avons pas de variables à interpréter dans la chaine. La différence entre les deux expressions suivantes :
$mouf = "Ma chaine sans variable";
$mouf = 'Ma chaine sans variable';