Et à mon grand désarrois, après rechargement de la page, j'ai bien été obligé de constater que cela n'avait strictement rien changé, bien au contraire, puisque les performances s'étaient encore plus dégradées.

Après avoir lancé un Putain merde fait chier ! bien senti dans le bureau afin d'évacuer un peu ma colère, j'ai donc cherché à comprendre ce qui pouvait bien se passer pour que ma solution ne donne pas le résultat escompté.

Mon premier réflexe a été de faire un appel à la commande top afin de définir le processus qui s'arrogeait l'ensemble des ressources du serveur et qui provoquait donc le ralentissement constaté.

Et si le changement d'architecture n'a pas augmenté les performances, il m'a cependant permis de constater que le coupable n'était pas Apache 2 mais bien PHP !

En effet, php-fpm permet de découpler totalement les processus PHP des processus de Apache 2, et cette granularité supplémentaire m'a permis de constater qu'un seul et unique processus PHP monopolisait totalement le serveur alors que les autres attendaient.

De plus, comme nous avions alloué un groupe de processus au site de e-commerce et un autre groupe distinct au site d'administration, nous avons pu conclure que le code responsable du ralentissement de l'ensemble de la solution provenait du site d'administration.

La mise en place de php-fpm n'avait donc pas résolu le problème de verrouillage de ressource introduisant une situation de compétition que j'avais diagnostiqué auparavant, mais elle m'avait cependant permis de confirmer mon diagnostique et de déterminer plus précisément le coupable.

Dans ce genre de situation, il faut mieux voir les aspects positifs, histoire de ne pas perdre le moral en se disant que nous venions de passer une journée de travail par les pertes et profits…

Cerise sur le gâteau, j'avais maintenant un numéro de processus à donner à manger à la commande strace qui ne regroupait pas à la fois Apache et PHP, et en conséquence, je pouvais avoir une visibilité plus nette et précise sur ce que pouvait bien être en train de faire ce processus trop gourmand.

Encore une fois, dans ce genre de situation, il faut vraiment voir le bon côté des choses…

La commande strace m'a donc permis d'obtenir la liste des appels systèmes effectué par le processus PHP en question, et j'ai alors été proprement estomaqué par le nombre d'appels au système de fichiers effectué par le processus.

En effet, ils représentaient à eux seuls la grande majorité du dialogue entre le processus et le système d'exploitation.

En résumé, le processus semblait passer son temps à demander au système de fichier si tel ou tel fichier existait bien, et dans l'affirmative, de lui en renvoyer le contenu, ce qui correspond au comportement typique de PHP lorsqu'on lui demande d'inclure un fichier notamment à l'aide des instructions include_once et require_once.

Une analyse un peu plus attentive nous a permis de constater qu'une partie d'entres eux était induite par une mauvaise configuration de PHP.

En effet, pour chaque fichier demandé par le mécanisme d'auto-chargement de classe ou via include et ses dérivés, PHP regardait tout d'abord dans le répertoire correspondant à pear et dans un autre répertoire sans aucun rapport avec notre code.

Et pour cause, la directive include_path défini par le fichier php.ini était initialisée avec les valeurs par défaut telles que définies lors de l'installation de PHP.

Nous avons donc corrigé la valeur de cette directive, et nous avons alors constaté une baisse significative du nombre d'appel au système de fichiers, sans pour autant que le volume de ces appels devienne raisonnable.

Nous avons alors commencé à nous intéresser au mécanisme d'auto-chargement de classe du site d'administration, et nous avons découvert que pour des raisons historiques, il était conçu de façon à pouvoir faire cohabiter plusieurs frameworks et qu'en conséquence, il lui était nécessaire d'effectuer un grand nombre d'appels au système de fichier pour localiser le fichier correspondant à la classe qui lui était demandé.

J'ai alors commencé à faire un peu de ménage, car certains mécanismes mis en place étaient redondants, et j'ai remplacé les appels à require_once et include_once respectivement par require et include lorsque cela était pertinent.

Mais malheureusement, cela n'a pas été suffisant puisque je ne suis pas parvenu à obtenir une baisse suffisante du nombre d'appels au système de fichiers.

Bien que je ne sois pas fan de ce genre de solution, je me suis donc résolu à développer le code nécessaire pour mettre en cache les chemins permettant d'accéder à chaque classe du site d'administration, afin que PHP n'ai plus besoin de multiplier les appels au système de fichiers pour localiser la classe demandée.

Une fois cela effectué, nous avons alors constaté une baisse très importante du nombre d'appel au système de fichier et une légère amélioration des performances.

Mais surtout, la suppression de ces appels nous a permis d'avoir à l'aide de strace une vision plus précise de ce que faisait notre fameux processus PHP.

Et là, d'un coup, j'ai eu l'illumination !