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: ` <?php //… while (list($key,$val) = each($array)){

} //… ?> `

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: $arian = implode(" | ",$array);

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: // $flag = false; while (list($key,$val) = each($array)){ //ou un foreach... comme vous voulez if($flag){ //ne passera jamais par là lors de la première itération... echo " | "; } $flag = true; echo '<a href="'.$val->url.'">".$val->title.'</a>'; } //

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

comments powered by Disqus