12 astuces d'optimisation de performance PHP
Par NiKo le mercredi 22 novembre 2006, 22:25 - Dev
- Lien permanent -
38 commentaires -
Tags :
Je suis tombé complètement par hasard (enfin, par celui des apports de Blogdigger) sur un article présentant 12 astuces pour optimiser les performances de son code PHP suite à une présentation sur le sujet d'Ilia Alshanetsky à la Zend Conference (les slides sont disponibles).
C'est tellement pertinent que je les reprends telles quelles ici, en français :
- Si vous pouvez déclarer une méthode statique
static, faites-le : les performances sont multipliées par 4. - Éviter les méthodes automagiques comme
__get,__setou__autoload. require_onceet son copaininclude_oncesont très coûteux.- Utilisez des chemins absolus dans les appels à
requireouincludequand vous le pouvez : PHP perdra moins de temps à résoudre les chemins système. - Utilisez
$_SERVER['REQUEST_TIME']plutôt quetime()pour obtenir le temps système. - Voyez si vous ne pouvez pas utiliser
strncasecmp,strpbrkandstriposplutôt que de recourir aux expressions régulières. preg_replaceest plus rapide questr_replacestr_replaceest bien entendu beaucoup plus rapide quepreg_replace[1], maisstrtrest 4 fois plus rapide quepreg_replace!- L'emploi de tableaux en tant qu'arguments des fonctions de remplacements de chaînes de caractères est plus couteux que l'utilisation multiple de cette même fonction chaîne par chaîne à remplacer.
- La suppression de la sortie d'erreur par l'emploi du caractère @ est très coûteuse.
$row['id']est 7 fois plus rapide d'accès que$row[id].- Les messages d'erreur en général sont coûteux.
- N'utilisez pas de fonctions à l'intérieur des boucles comme
for ($x=0; $x < count($array); $x++): ici la méthodecount()est appelée à chaque itération.
Notes
[1] Le billet lié est erroné sur ce point, et je l'avais traduit tel quel. La lecture des slides de la conférence m'aura permis de réctifier le tir.
38 commentaires (Ajouter un commentaire)
Ah ben j'vois que t'as fait un billet dessus, fresh !
Et le mieux encore, c'est de d'abord profiler son application, histoire de voir qu'est-ce qui fait vraiment ramer, avant de se lancer dans d'la premature optimization
Genre avec xDebug (http://xdebug.org/)
euh pour une exception sur un fopen, il faudrait peut être regarder du coté de la spl : http://lu.php.net/spl notamment l'objet splFileObject, http://www.phpro.org/tutorials/Intr...
utiliser une api orientée objet quand on le peut, saimieux!
NB... J'aime programmer comme je veut :
1. Créer vos propres fonctions pour calculer le temps d'exécution.
2. Optimiser vos pages à un certain temps d'exécution ( < 15 secondes ? )
3. Créer vos propres objets PHP et JavaScript.
4. Documenter bien vos lignes codes.
Je préfère lire que str_replace [faster than] preg_replace... bien que ça me semblait le seul truc invraisemblable parmi le reste de faits (comme le 12
)
>concernant la 7 (preg_replace est plus rapide que str_replace), je suis plus que septique... voir
>j'y crois pas du tout...
En fait, c'est str_replace plus rapide que preg_replace plus rapide que ereg_replace.
Et une fois que votre code est pile poil optimisé, n'oubliez pas d'utiliser un cache d'exécution php comme mmcache ou zend accelerator, ça dépote
Hi,
Concernant l'opérateur @, c'est un des plus gourmand de l'alphabet PHP. A chaque fois cela correspond à :
$old = ini_set(“error_reporting”, 0);
action();
ini_set(“error_reporting”, $old);
La meilleur solution consiste à utiliser la bonne configuration en fonction de votre étape de développement :
Dev :
Error au max
Affichage et log des erreurs
Prod :
Error au max (moins E_Notice eventuellement)
Pas d'affichage des erreurs
Log des erreurs
éventuellement ne pas loguer n fois la même erreur (ignore_repeated_errors = On)
++
Cyruss
Précision pour la 3, c'est moins vrai avec PHP 5.2 des optimisations ont été apportées (Optimized require_once() and include_once() by eliminating fopen(3) on second usage. (Dmitry))
La 10 est logique car comme indiqué dans un autre commentaire il cherche une constante nommé id. En développant avec E_ALL en niveau de reporting d'erreur cela se voit de suite
Juste pour ajouter que (en PHP5) foreach peut travailler avec des références :
<?php $arr = array(1, 2, 3, 4); foreach ($arr as &$value) { $value = $value * 2; } // $arr vaut maintenant array(2, 4, 6, 8) ?>cf : http://fr.php.net/manual/fr/control...
Plus d'excuse pour ne pas utiliser foreach ! ;p
yop!
perso je prefere utiliser les méthodes automagiques comme __get, __set ou __autoload, utiliser require_once et son copain include_once qui sont très coûteux certes, utiliser time() plutot que $_SERVER['REQUEST_TIME'] pour obtenir le temps système, tout comme array_push plutot que $toto[] = 'foo'.... bref tout ca pour dire que je pense que c'est insignifiant et que je prefere pondre un code joli et chercher des optimisations ailleurs.
nb: quand a la 8, je ne suis pas convaincu... tous les benchs se contredisent... selon la taille du tableau notament.
ceci dit c'est toujours agréable de lire des choses comme ca.
hugues
La 8. me laisse perplexe. J'ai retrouvé un bench (donc à ne pas prendre pour agrent comptant) sur le sujet :
http://www.estvideo.net/dew/index/2...
(d'où mon ps !)
Et comme je suis vachement sympa, une proof of concept: http://more.zubrowka.org/~ash/error...
(ps: ounaide, mais comme t'as fait une faute à mon prénom je poste quand même)
Geofrey> Trouvé. Sinon je suis d'accord que les gros tableaux de données ne devraient pas être itérés via
foreach.Pour les autres qui repprochez à cette liste de donner envie de sacrifier les bonnes pratiques de conception sur l'autel de la performance à tout prix, sâchez que ce n'était là nullement mon intention (ceux qui me lisent régulièrement le savent bien. Ou pas.)
Mais je peux vous assurer que quand vous vous retrouvez à hériter d'un code que vous n'avez pas commis, truffé de problèmes de perfs sur des serveurs quadri-processeurs à 8 Go de RAM et qu'il est bien entendu hors de question de tout redévelopper from scratch, ce genre de petites astuces valent de l'or.
NiKo: tu peux faire un error_handler qui lance des exceptions (du moins j'avais lu un truc sur ce sujet) et pour le foreach, quand on t'obligera a itérer un tableau de 4Mo sans toucher le memory_limit, tu seras bien content d'utiliser autre chose que foreach
@Olivier et point 2 > c'est exactement ce que disait mon prof de génie logiciel (y a 10 ans snif
) qui disait de manière volontairement *provocante* : "les performances ne doivent pas en aucun cas obliger le développeur à renoncer à un développement évolutif et bien conçu".
De manière générale, penser performances au moment de la conception, c'est bien et somme toute peut-être assez rare. Le danger de ce type de liste est (comme tout type de recommandation) surement son application de manière aveugle.
Le truc con c'est qu'on peut pas try/catcher une erreur sur un fopen par exemple. Ça serait bien que ça vienne un jour ce genre de choses.
Sinon,
foreachc'est pour moi trop pratique pour penser une seule seconde en économiser le coûtOui c'est dotclear le moteur de blog qui utilise @, et ça m'a fait perdre quelques cheuveux dernièrement (j'aurai un bug report a faire a ce propos d'ailleurs quand j'aurai 5 minutes)
Et donc pour approfondir un peu, j'estime que rien ne justifie l'utilisation du @ si on tient compte du fait, premièrement, qu'un error_handler peut catcher toutes les erreurs (sauf PARSE ERROR bien sur), et deuxièmement, qu'il est universellement reconnu comme une bonne pratique de désactiver l'affichage des erreurs en production.
D'autres part, je tiens à préciser que certains propos que je tiens quand on parle de certaines choses (le @ en fait partie) dépassent souvent mes pensées, et je m'en excuse platement (bien que personne ne m'en ait fait le reproche, ce qui m'épate un peu pour le coup).
J'ajouterai par ailleurs à la liste d'Olivier le magic_quotes_runtime Off (en attendant sa suppression définitive dans PHP6 :/)
En parlant de for et de foreach, saviez vous que foreach travaille sur un duplicata du tableau qui lui est passé ? Ce qui signifie qu'en utilisant foreach, on "gaspille" un peu de mémoire (peu important en général, mais bon a se souvenir quand même), sauf a priori quand on utilise foreach sur un objet "Iterable".
voila voila
La liste est sympa, d'ailleurs, le count() dans le for j'avoue le pratiquer souvent, c'est mal
(d'un autre côté j'utilise très peu for et lui préfère foreach quand je peux).
C'est dotclear le moteur de blog qui utilise @ ? Je reconnais l'utiliser un peu mais dans des cas où je n'ai pas vraiment le choix, ça reste quand même assez rare, j'ai horreur de ça.
Le point 2 est une connerie par contre, autant revenir à php4. L'autoload est une feature vraiment pratique et le poil de cul de perf qu'on perd avec on le gagne en occupation mémoire et on n'utilise plus de require ou require_once que quand c'est nécessaire. Bien sûr, je parle d'un autoload qui ne va pas regarder dans le filesystem mais qui utilise un tableau global.
J'ai envoyé l'autre jour ces paramètres php.ini sur une liste, c'est un bon début pour ceux qui veulent faire du code qui marchera bien d'un environnement de dev à un environnement de prod.
short_open_tag = Off
allow_call_time_pass_reference = Off
error_reporting = E_ALL | E_STRICT
display_error = On
register_globals = Off
magic_quotes_gpc = Off
allow_url_fopen = Off
Encore pleins de trucs que j'ignorais. J'en profite pour garder ta page Blogmarks phpBestPractices sous la patte.
str_replaceétait la méthode la plus rapide pour le remplacement de chaîne (mais aussi la plus basique et la plus limitée). À bencher.Ces petits astuces sont intéressantes, et ce sont de bonnes habitudes à prendre, mais je ne pense plus que l'optimisation d'un code passe réellement par là aujourd'hui, si ce n'est pour quelques applications pour lesquelles je ne suis pas sûr que PHP soit le langage le plus adéquat. Pour moi, l'optimisation passe aujourd'hui avant tout par une bonne réflexion au moment de la conception, et par une utilisation raisonnée des différents modèles de conception. A vouloir à tout prix faire de l'objet, du MVC, etc, on se met à écrire des usines à gaz là où il y a quelques années quelques lignes de code suffisaient.
Je ne remet pas en cause ces méthodes de conception, elles présentent de nombreux avantages, mais ont à mon avis des impacts lourds sur les performances, et c'est plutôt de ce côté là qu'il faudrait creuser. Enfin AMHA.
Ensuite, si vraiment on veut tuner les performances de son code au cycle prêt, l'assembleur et le C sont des langages fort agréables (nostalgie, nostalgie)
PS: NiKo: le lien sur blogmarks serait plutôt http://blogmarks.net/marks/tag/best...
Bonjour,
concernant la 7 (preg_replace est plus rapide que str_replace), je suis plus que septique... voir j'y crois pas du tout...
Effectivement, interessante liste. De meme que les différents liens de benchmark sur les perf.!
Merci... à méditer, donc...
0. Ne pas faire de PHP c'est la solution ultime pour pas subir de process PHP!
ok ->
Geoffrey> Tu peux développer sur le point 9 ?
L'utilisation du @ permet de gérer des erreurs d'une manière un peu plus "sexy" que de se taper une bonne grosse insulte PHP parce que MySQL n'est pas joignable. Une autre méthode moins gourmande à suggérer peut être ?
3/ un lien explicatif : http://www.ipersec.com/index.php?q=...
12/ on peut faire ca :
for ($x=0, $count = count($array); $x < $xount; $x++) { }Sympa pour le rappel des autres, c'est toujours bon a relire
Voici une autre série de bonnes pratiques : http://www.noplay.net/Bonnes-pratiq...
Justin Patrin (un gars qui travaille sur plusieurs packages pear.php.net) a publié sur son wiki un comparatif de performances de concaténation de chaines :
http://pear.reversefold.com/strings...
A lire aussi.
La 10 est d'une logique implacable, si on considère la 11:
$row[id]cherche la constanteid, qui n'existe pas: perte de temps dans la recherche inutile + perte de temps dans le message d'erreur (cf 11)La 9 me donne une raison de plus de maudire sur 20 générations les utilisateurs complètement débiles de cette feature complètement stupide (je ne citerai pas un moteur de blog super connu qui en fait usage mais on l'aura reconnu).
La 8 m'épate par contre :o
Sinon oui globalement, c'est assez logique, mais on y pense pas forcément (et puis se passer de
require_onceok, mais bon, faut voir si le gain de performance justifie les contraintes qu'on se rajoute)Bref, sympa, mais à méditer avant d'en tirer des conclusions hatives je pense
Azurams> Un début de bout de réponse par là.
Merci pour ces petites astuces!
Connaissez vous un site présentant "des" bonnes pratiques et optimisations en PHP , avec si possible des explications et des mises en contexte?
+1 pour jblanche...
La 10 est aussi impressionnante.
Merci pour ces conseils,
certains sont logiques(12), d'autres moins.
J'aimerais bien savoir pourquoi un tel gain de performance grâce au static par exemple.
le douzième commandement vaut pour tous les langages utilisant le 'for'...
sinon, c'est très bien de publier ce genre de post
merci.
La discussion continue ailleurs
12 astuces pour optimiser ses scripts php
Niko de "prendre un café" publie 12 astuces pour optimiser son script php...
Quelques astuces pour PHP
Développant régulièrement des sites en PHP, je suis tombé aujourd’hui sur le site de Prendre un Café qui publie 12 règles à suivre pour optimiser le PHP. Je les copie ici: Si vous pouvez déclarer une méthode statique static, faites-le......