PHP optimisations et astuces
On vient d'en discuter avec Guillaume, et on est en train de le bloguer en même temps :) Tout d'abord pour vous parler de phpbench qui vous présente régulièrement des benchmarks de différentes méthodes PHP. Vous y découvrirez par exemple, et cela va être sujet à notre discussion juste après, que while (list($key,$val) = each($array)) est largement plus rapide que foreach ($array as $key=>$val). Ou encore que les if..elseif..else sont plus rapide que les switch/case... bref, allez lire la page et rafraichissez de temps en temps pour vous assurer des valeurs.
Mais revenons à notre discussion. Voyez ce petit bout de code:
A priori, ce code est très rapide, bien plus que foreach... mais avec un itérateur... ça ne marche pas. Vous avez deux solutions et il faudra vérifier laquelle sera la plus lente: soit revenir à foreach, soit faire:
$array = iterator_to_array($array);
Voir http://fr.php.net/manual/fr/function.iterator-to-array.php qui nous présente la méthode. Dans l'absolu, le code while list est utilisable... mais est-ce que la fonction iterator_to_array est si lente que cela serait plus lent qu'un foreach à l'ancienne ? Je ne sais pas, je vais faire le bench ce soir.
Une astuce qui est tombé juste dans notre conversation, c'est la méthode la plus simple de joindre des chaînes avec un séparateur.
Prenons l'exemple d'une série de lien dans un fil d'Ariane: "index | contact | links | about". Si les valeurs proviennent d'un tableau, il peut être judicieux de simplement faire:
C'est simple rapide et efficace... mais lorsque nous passons dans un itérateur qui a des valeurs complexes à concaténer, cela devient vite fastidieux de vérifier si nous sommes dans le dernier élément et donc si il ne faut pas ajouter le dernier "pipe" à la fin. D'autant qu'il va falloir créer des liens, donc des balises... etc...
Imaginons cette structure:
class link {
public $url;
public $title;
function __construct($url,$title){
$this->url = $url;
$this->title = $title;
}
function create($url,$title){
return new self($url,$title);
}
}
$array = array (
link::create('index.php','Home'),
link::create('index.php/contact','Contact'),
link::create('index.php/about','About'),
);
Nous avons donc un tableau d'objet. Voici la méthode la plus simple à mettre en place:
Regardons comment cet algo fonctionne. Première itération, $flag est à FALSE, donc on affiche pas de "pipe" (|). On écrit le premier lien et on continue. $flag est passé à TRUE.
Seconde itération, on écrit le "pipe" puisque $flag est vrai. Et on écrit le second lien.
Troisième et dernière itération, on écrit le "pipe", et le troisième lien... et c'est fini.
Donc, pas de pipe en début et en fin de chaine, on a un "implode" manuel qui est nickel. Le fait d'utiliser un booléen, de tester une "vérité" au début et de ne pas faire de test sur la taille de $array réduit fortement la charge.
Il faut penser à ce genre d'astuce le plus souvent possible. A la longue, après des milliers de lignes de code, cela rend votre site, votre application... bien plus rapide.
Merci Guillaume de m'avoir lancé sur le sujet ;)
Voir: http://apprendrelinux.blogspot.com/2008/06/afficher-un-lment-chaque-passage-dans.html
Trackbacks
Pour ajouter un trackback (retrolien) sur ce ticket, utilisez cette adresse: http://www.metal3d.org/index.php/trackback/default/tb?id=blog%2F81


Je crois qu'il y a mauvaise interprétation des résultats.
Le foreach est "plus" rapide que le while ($list () = each()) (dans tous les cas)
Alors là, on est deux à lire ton commentaire, à retourner sur phpbench... et à sauter au plafond...
Hier, tous les while étaient largement (mais alors largement) plus rapide...
Je vais certainement faire les bench moi même...
Solution trouvé par Guillaume, l'auteur de phpbench à écrit cela dans la nuit:
"Given that the previous version of the tests have been very controvercial and incorrect, I must appologise for forgetting to implement the reset() function to allow the while() loops to start from the beginning instead of the end. Thanks to Anthony Bush for spotting this out."
Voilà qui est dit
Et dire que tu avais réussi à me convaincre que le While était plus rapide ... snif :)
Lol j'en étais convaincu aussi :p
Merci Gérald pour ton premier commentaire. Sans cela, j'aurai laissé trainé un mensonge sur mon blog... houuu la honte
Ce qui m'a fait tiquer, c'est que j'avais très récemment joué a faire ces mesures de mon coté, et que j'étais tombé sur des conclusions à l'inverse de ce que tu présentais :-)
Je suis comme St Thomas, je ne crois que ce que je vois !