# Régler OPcache et PHP-FPM pour un site WordPress qui encaisse la charge

> Guide pratique des réglages OPcache et PHP-FPM essentiels sur WordPress, avec le piège classique du cache qui ne se recharge jamais en production.

- Auteur : Clément Hadrot
- Publié le : 2021-02-09
- Mis à jour le : 2021-02-09
- Catégorie : Performance
- URL : https://wpmoderne.dev.wordpress-developpement.fr/performance/opcache-php-fpm-reglages-wordpress/

## L’essentiel

- OPcache évite de recompiler le PHP à chaque requête, gain immédiat et gratuit
- validate_timestamps à 0 impose un rechargement manuel du service
- pm.max_children se calcule à partir de la RAM réellement disponible

Depuis le passage à PHP 7, beaucoup de développeurs WordPress ont pris l'habitude de considérer que « PHP est rapide » et de chercher les gains de performance ailleurs : cache de page, cache d'objets, CDN. C'est oublier deux réglages qui se trouvent à la racine même de l'exécution de PHP et qui, mal configurés, peuvent ruiner tous les efforts faits en amont : OPcache et le pool PHP-FPM.

Ces deux composants ne sont pas des extensions WordPress, mais des réglages serveur. C'est justement pour ça qu'ils sont souvent ignorés par les développeurs qui n'ont pas la main sur l'infrastructure, et qu'ils réservent quelques mauvaises surprises à ceux qui les découvrent en production, généralement le jour où un article ne se met plus à jour malgré toutes les purges de cache imaginables.

## Ce qu'OPcache fait réellement

PHP est un langage interprété : chaque fois qu'un script est exécuté, il doit être analysé et compilé en *opcodes*, un langage intermédiaire compris par le moteur Zend. Sans OPcache, cette compilation a lieu à chaque requête, pour chaque fichier PHP appelé, ce qui représente un travail répétitif et coûteux sur un site WordPress qui charge des dizaines de fichiers par page (cœur, thème, extensions).

OPcache, intégré à PHP depuis la version 5.5, conserve ces opcodes compilés en mémoire partagée. Tant qu'un fichier n'a pas changé, PHP-FPM sert directement la version compilée sans repasser par l'étape d'analyse. Le gain est immédiat, gratuit, et ne nécessite aucune modification du code WordPress.

## Les réglages OPcache essentiels dans php.ini

```
[opcache]
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.save_comments=1
```

- `opcache.memory_consumption` : la mémoire allouée au cache d'opcodes, en Mo. 128 Mo suffisent pour un petit site, mais un WordPress avec de nombreuses extensions et un thème enfant volumineux dépasse vite ce seuil ; surveillez le taux d'utilisation avec `opcache_get_status()`.
- `opcache.interned_strings_buffer` : mémoire dédiée aux chaînes de caractères répétées dans le code (noms de fonctions, de classes). WordPress en génère énormément, 16 Mo est un bon point de départ.
- `opcache.max_accelerated_files` : le nombre maximal de fichiers PHP distincts pouvant être mis en cache. Un WordPress avec une dizaine d'extensions actives dépasse facilement 10 000 fichiers ; visez large, 20 000, pour ne jamais saturer ce plafond.

> L'essentiel à retenir : OPcache évite de recompiler le PHP à chaque requête, gain immédiat et gratuit ; validate_timestamps à 0 impose un rechargement manuel du service ; pm.max_children se calcule à partir de la RAM réellement disponible

## Le piège du cache qui ne se recharge pas

C'est le réglage le plus mal compris, et celui qui provoque le plus d'incidents en production : `opcache.validate_timestamps`. Quand il vaut `1` (la valeur par défaut), OPcache vérifie à chaque requête si le fichier source a été modifié depuis sa dernière compilation, en comparant l'horodatage du fichier. Cette vérification a un coût, certes faible, mais réel.

La tentation, pour gratter les derniers pourcentages de performance, est de passer `opcache.validate_timestamps` à `0`. OPcache ne vérifie alors plus jamais si un fichier a changé : il sert indéfiniment la version compilée en mémoire, même si le fichier PHP source a été modifié sur le disque une heure, un jour ou une semaine plus tôt.

> Nous avons vécu ce piège sur un client : une correction urgente déployée sur le thème n'avait strictement aucun effet visible, alors que le fichier sur le disque était bien le bon. La cause : `validate_timestamps=0` en production, sans procédure de rechargement d'OPcache dans le pipeline de déploiement. Le cache d'opcodes tenait encore la version d'avant, compilée trois jours plus tôt.

Si vous désactivez `validate_timestamps` pour la performance en production (ce qui reste pertinent sur un site à fort trafic et déploiements maîtrisés), il faut impérativement forcer un rechargement du cache à chaque déploiement, par exemple avec `opcache_reset()` appelé depuis un script de déploiement, ou plus simplement en redémarrant le service PHP-FPM :

```
sudo systemctl reload php7.4-fpm
```

Avec `validate_timestamps=1`, réglez `opcache.revalidate_freq` (en secondes) pour espacer les vérifications sans les supprimer complètement : une valeur de 2 à 5 secondes offre un bon compromis entre réactivité et performance sur un site en développement actif.

## Dimensionner correctement PHP-FPM

OPcache accélère l'exécution de chaque requête PHP individuelle, mais c'est PHP-FPM qui détermine combien de requêtes peuvent être traitées *en même temps*. Le réglage central se trouve dans le pool (souvent `/etc/php/7.4/fpm/pool.d/www.conf`) :

```
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8
pm.max_requests = 500
```

`pm.max_children` est le réglage le plus critique : c'est le nombre maximal de processus PHP pouvant tourner simultanément. Le calculer au hasard, ou le copier d'un tutoriel générique, est une erreur fréquente. La formule de base :

```
pm.max_children = (RAM disponible pour PHP-FPM) / (RAM moyenne consommée par un processus PHP)
```

Pour mesurer la consommation réelle d'un processus PHP-FPM sous charge, la commande suivante donne une bonne estimation :

```
ps -ylC php-fpm7.4 --sort:rss
```

Sur un serveur disposant de 2 Go dédiés à PHP-FPM, avec des processus WordPress consommant en moyenne 40 à 50 Mo chacun (WooCommerce et les constructeurs de pages font grimper cette moyenne), on obtient un `pm.max_children` raisonnable autour de 35 à 40. Un réglage trop bas provoque une file d'attente et des erreurs 502 sous charge ; un réglage trop haut risque de saturer la RAM du serveur et de déclencher le tueur OOM du noyau Linux.

## Vérifier que tout fonctionne

Pour observer l'état réel d'OPcache en production, une extension comme Query Monitor ou une simple page de diagnostic PHP utilisant `opcache_get_status(false)` permet de vérifier le taux d'utilisation mémoire et le nombre de fichiers en cache. Côté PHP-FPM, activer le *status page* (`pm.status_path = /status`) donne accès en temps réel au nombre de processus actifs, en attente, et au nombre de requêtes ayant atteint la limite de processus disponibles.

## En résumé

OPcache et PHP-FPM ne sont pas des réglages qu'on fixe une fois pour toutes et qu'on oublie. Un bon dimensionnement de `pm.max_children` évite les pannes sous charge, et une gestion réfléchie de `validate_timestamps` évite l'autre piège, plus sournois : celui d'un correctif déployé qui ne semble jamais prendre effet. Dans les deux cas, la clé est la même : mesurer avant de régler, et ne jamais copier une configuration trouvée en ligne sans l'adapter à la RAM et au trafic réels du serveur.
