TUTORIEL PHP 
Optimiser vos applications PHP
La popularité grandissante du Web met une pression croissante sur les logiciels et le matériel utilisé pour les applications. Cet article va vous donner les tuyaux pour réduire la charge de vos serveurs, et augmenter la capacité de vos applications sans avoir à vous ruiner en mises à jour matérielles. (30/03/2004)

(fourni par Direction PHP)

<< 1. Commencer | 2. Configuer PHP | 3. Optimiser php.ini
4. Au-dela de la configuration | 5. Cacher en mémoire


Optimisation du fichier php.ini
Il est maintenant temps de se tourner vers les directives de configuration PHP.INI, qui peuvent aussi être utilisées pour améliorer la performance générale de vos scripts.

Je commencerai par l'option register_globals, qui est déjà désactivée par défaut avec PHP 4.2.0. Toutefois beaucoup de gens l'ont toujours réactivée, car sa configuration n'a jamais été mise à jour lors de la mise à jour de leur version PHP. Cette option pousse PHP à enregistrer un nombre potentiellement grand de variables basées sur les entrées utilisateur et système, tout en rendant possible certains méthodes d'assaut. Il est conseillé de garder cette option désactivée et d'utiliser les super-globales toutes prêtes, pour accéder aux données passées par l'utilisateur dans les demandes POST et GET ou les cookies de navigation.

Vous pouvez optimiser davantage la création de variables basées sur les entrées de l'utilisateur en changeant la directive variables_order. Elle indique quelle source d'information du client doit être utilisée pour engendrer les super-globales, ainsi que l'ordre dans lequel on devrait les traiter quand on construit $_REQUEST, qui est un résultat cumulatif des contenus d'autres super-globales. Par défaut, la valeur de cette option est ESGPC. Cela signifie que les données venant de l'environnement système, de l'environnement serveur et de GET/POST/COOKIE sont enregistrés dans cet ordre. Le stockage et la création d'éléments de tableau dans les super-globales peut prendre une grande quantité de mémoire, et aura un impact négatif sur chaque demande. Par conséquent vous pouvez améliorer la performance générale de votre système en réduisant le nombre de créations de super-globales. Dans la plupart des cas, cela signifie que vous pouvez mettre la valeur de variables_order simplement à GPC, de façon à ce que les données passées par l'utilisateur dans les requêtes GET/POST ou par les cookies soient stockées dans les super-globales.

La conséquence de ce choix est une accélération de la fonction d'analyse en entrée, et une plus petite occupation en mémoire. Si vous avez besoin d'accéder aux paramètres système ou aux variables d'environnement, vous pouvez les lire avec la fonction getenv(), ce qui ne vous pénalisera pas.

En plus des tableaux super-globaux, PHP crée aussi des variables spéciales qui sont utilisées pour stocker les arguments qui sont passés en ligne de commande. Dans un environnement web, vos scripts PHP ne recevront jamais ce type d'arguments, et donc, la création de ces variables est parfaitement inutile. Vous pouvez donc désactiver l'option register_argc_argv, qui est responsable de leur création : cela va accélérer vos scripts. Gardez en tête que si vous utilisez la version CLI de PHP, vous aurez besoin de laisser cette option activée, car dans ce contexte, les variables seront passées en ligne de commande.

Lorsque vous analysez les données d'entrées de votre script, PHP va automatiquement protéger les données pour éviter que les utilisateurs n'injectent des caractères spéciaux, qui conduiraient à des comportements inattendus de certaines parties de votre script. Cette protection n'est pas toujours utile, car toutes les données provenant de l'utilisateur ne conduisent pas à un tel trou de sécurité. Il est donc plus performant de désactiver la directive magic_quotes_gpc et d'assurer la protection de vos données manuellement, avec la fonction addslashes(), ou en utilisant toute fonction adaptée à votre application : par exemple, vous pourriez sécuriser les données qui seront transmises au Shell avec la fonction escapeshellcmd(), tandis que mysql_escape_string() sera utile avec les requêtes envoyées à MySQL.

Les avantages à assurer votre propre protection sont nombreux : tout d'abord, vous ne protégez que ce dont vous avez besoin, et donc, vous réduisez le temps que PHP passe sur l'analyse des données d'entrée. Vous économisez de la mémoire, car le processus de protection va réserver deux fois plus de mémoire que d'habitude, pour stocker la chaîne originale, et la chaîne traitée. De plus, vous obtenez une application mieux conçue, qui ne dépend pas de la configuration de la plate-forme sur laquelle elle fonctionne. Elle sera capable de s'installer normalement même sur un environnement où magic_quotes_gpc est désactivée.

Il y a d'autres directives de configuration qui sont importantes pour l'optimisation de votre serveur. Par défaut, chaque requête PHP émet un entête HTTP appelé X-Powered-By, ce qui fait perdre un peu de temps à PHP. Cet entête est totalement inutile, et en fait, les seules personnes qui s'intéresseront à cet entête sont celles qui chercheront à pénétrer sur votre système en se basant sur votre configuration. Elles commencent par connaître la version de PHP pour en exploiter de mauvaises configurations classiques. Il est donc prudent de désactiver la directive expose_php. Non seulement vous allez rendre les attaques sur votre système un peu plus difficiles, mais en plus vous économisez de la bande passante et augmentez les performances de PHP.

En parlant d'envoi de données à vos visiteurs, il existe un autre domaine où une configuration correcte de PHP est très efficace. Par défaut, PHP va envoyer les données au navigateur dès que votre script lui en envoie : cela déclenche de nombreuses opérations d'écriture et d'envoi à travers le réseau. Le processus se ralentit pour les grandes pages, car de nombreux appels système seront sollicités pour envoyer tous ces petits paquets. De plus, certains navigateurs vont rafraîchir l'affichage de la page à chaque réception, et cela rendra la navigation de votre visiteur plus lente et moins agréable. Pour pallier ce problème, il suffit de mettre en buffer les données à envoyer à travers le réseau, et de les envoyer en groupe : cela réduit le nombre de sollicitations des sockets, et accélère le rendu chez le client.

Les buffers de sorties sont activés et contrôlés par la directive output_buffering, qui vous permet de spécifier la taille de mémoire utilisée par le script pour le buffer. Idéalement, vous allez rendre ce buffer aussi gros que la taille moyenne de vos pages. De cette façon, la majorité de vos pages seront envoyées en une seule fois. Mais attention, ne créez pas de buffers trop grands, car chaque instance de PHP va réserver un tel buffer : avec un nombre croissant de processus fonctionnant simultanément, vous risquez de consommer toute la mémoire disponible.

Une autre solution qui va accélérer l'envoi des données à l'utilisateur est la compression. PHP supporte la compression GZIP à la volée avec les buffers de sortie : les données seront compressées avec GZIP et reconnues par la majorité des navigateurs modernes. Pour ces derniers, la compression va réduire la taille de la page d'un ordre de grandeur. Les pages compressées sont particulièrement utiles pour les internautes ayant une connexion lente : dans ce cas, cela peut leur économiser beaucoup de temps de transfert, et dans le même temps, libérer plus rapidement votre serveur pour qu'il serve un autre client. En conséquence, vous augmentez le nombre d'internautes que vous pouvez servir. Un autre aspect intéressant de cette technique est la réduction du trafic sur votre bande passante : j'ai vu des sites réduire leurs coûts en bande passante de 40 à 50%, uniquement en utilisant la compression à la volée.

Mieux encore, cette fonctionnalité ne requiert aucune modification du code des scripts, et peut être activée en donnant simplement la valeur de ob_gzhandler à la directive output_handler, dans le fichier php.ini. Sinon, vous pouvez l'activer individuellement pour les hôtes virtuels qui vous intéressent dans httpd.conf ou bien dans des dossiers spécifiques avec les fichiers .htaccess ; enfin, vous pouvez aussi utiliser la commande ini_set() dans les scripts qui génèrent beaucoup de volume. Soyez conscients que la compression à la volée consomme des ressources processeur, et vous serez témoin d'une élévation de la charge sur votre serveur. A vous de voir si vous pouvez le tolérer. Dans la plupart des cas, la réduction de la bande passante et des temps de chargement plus courts l'emportent sur la charge du processeur.

Parfois, vous utiliserez PHP non seulement pour envoyer des données, mais aussi pour en lire depuis des sources distantes : par exemple, lorsque vous programmez un client réseau, comme une application email, qui lit les messages sur le serveur IMAP.

Dans ces situations, il est important de se rappeler que Internet n'est pas un moyen de stockage local, et que lire des données peut être très lent. Vous ne souhaitez pas passer trop de temps à attendre que la ressource distante réponde, et bloque votre serveur. Pour éviter les attentes infinies, vous devriez utiliser la directive default_socket_timeout, qui vous permet de définir le nombre de secondes d'attente de PHP avant qu'il n'abandonne la lecture des données. C'est particulièrement vrai dans un environnement web, car le temps que votre script attend des informations est du temps et des ressources en attente pour le serveur : il ne peut pas servir d'autre requêtes avec ce processus. Il lui faudra peut-être lancer d'autres processus pour pallier à ce manque et cela ne manquera pas d'augmenter la charge du serveur.

En plus de requêtes distantes, vous pourriez aussi travailler avec des sockets locales, comme pour une connexion à une base de données. Paramétrer votre connexion est très important, car cela vous évitera des embouteillages de connexion, qui risquent de dégrader fortement les performances, et vous conduire à des connexions refusées et des pages en ruine. Je vous recommande vivement d'utiliser les directives max_links et max_persistent qui existent dans la plupart des interfaces de bases de données pour spécifier le nombre de connexions que PHP peut conserver ouvertes simultanément. Par défaut, ces directives valent -1, ce qui signifie : pas de limite. Dans la plupart des situations, ce n'est pas une bonne idée, car PHP risque d'essayer d'ouvrir plus de connexion que votre serveur ne peut accepter. Cette directive est particulièrement importante pour les connexions persistantes, car cela conduit rapidement à ce que chaque processus Apache ait une connexion particulière à la base de données. Il est absolument critique de s'assurer que les connexions persistantes ne consomment pas toutes les connexions possibles sur le serveur de base de données, car ce dernier finirait par refuser toutes les autres connexions.

Dans de nombreux cas, par exemple si vous avez un serveur mutualisé, il est prudent de désactiver les connexions persistantes avec la directive allow_persistent. Cela va convertir automatiquement toutes les tentatives de création d'une connexion persistante en une connexion classique, et cela aidera à limiter les dégâts sur le serveur.

Les directives de configuration de PHP proposent aussi plusieurs moyens pour limiter les opérations de PHP peut exécuter, comme l'accès aux fichiers ou la quantité de mémoire allouée à l'interpréteur. Ces options sont très pratiques pour un environnement partagé, où vous devez garder les utilisateurs dans leur pré carré, et vous assurer qu'ils n'abusent pas du système. Mais sur un serveur dédié, où vous contrôlez la majorité du code PHP ainsi que les utilisateurs, ces options ne font que ralentir le serveur. Pour des raisons de performances, les directives safe_mode, open_basedir et memory_limit sont inutiles en environnement dédié : les vérifications supplémentaires qu'elles imposent sont peu économiques et conduisent à une perte de performances.

<< 1. Commencer | 2. Configuer PHP | 3. Optimiser php.ini
4. Au-dela de la configuration | 5. Cacher en mémoire
 
Ilia Alshanetsky pour JDN Développeurs
 
Accueil | Haut de page