Pourquoi les valeurs par défaut ne suffisent pas pour Drupal
PHP compile chaque fichier .php à chaque requête, à moins qu'OPcache ne serve le bytecode en cache. La valeur par défaut de opcache.max_accelerated_files est 10 000. Une installation Drupal 10 avec un profil de modules courant dépasse facilement 25 000 fichiers. Résultat : des fichiers évincés du cache, des compilations inutiles, une latence qui s'accumule.
Le realpath cache fait la même chose pour les chemins de fichiers : Drupal résout des milliers de chemins à chaque bootstrap. Avec un cache trop petit ou un TTL trop court, le système de fichiers est interrogé pour des chemins déjà résolus.
Le préchargement pousse le problème un cran plus loin : les classes les plus utilisées sont chargées au démarrage de PHP-FPM et restent en mémoire pour toutes les requêtes. Zéro compilation, zéro lecture de fichier.
OPcache : les paramètres à ajuster
Un bloc de configuration adapté à Drupal 10 ou 11 sur PHP 8.x, avec les raisons qui justifient chaque valeur.
; OPcache — production Drupal
opcache.enable=1
opcache.enable_cli=0
; 256 Mo pour les sites standards, 512 pour les grosses bases de code
opcache.memory_consumption=256
; Buffer pour les chaînes internées (noms de fonctions, clés de tableau, etc.)
opcache.interned_strings_buffer=32
; Couvre le nombre de fichiers PHP d'une installation Drupal avec contrib
opcache.max_accelerated_files=30000
; En production : désactiver la vérification des timestamps
; À combiner avec un reset au déploiement
opcache.validate_timestamps=0
; Obligatoire : Drupal utilise les annotations dans les docblocks
opcache.save_comments=1
; Désactiver la vérification de cohérence du bytecode en prod
opcache.consistency_checks=0
; Huge pages : gain si le kernel le supporte (Linux, transparent hugepages activé)
opcache.huge_code_pages=1
save_comments=1 : la ligne qu'on ne peut pas couper
Drupal utilise les annotations PHP dans les docblocks pour déclarer les plugins, les routes, les définitions d'entités. Passer save_comments=0 casse le système d'annotations. Ce n'est pas négociable.
validate_timestamps=0 : gain réel, contrainte réelle
Désactiver la vérification des timestamps signifie que PHP ne relit plus le fichier source pour vérifier s'il a changé. Sur un serveur chargé, c'est une réduction mesurable des appels stat(). La contrepartie : PHP ne voit plus les modifications de fichiers. Un déploiement sans reset d'OPcache sert du vieux bytecode.
Realpath cache : deux paramètres, un impact direct
realpath_cache_size=4096K
realpath_cache_ttl=3600
La valeur par défaut de realpath_cache_size est 4 Mo depuis PHP 5.6. Pour Drupal, c'est généralement insuffisant : le bootstrap parcourt les chemins de modules, de thèmes, de bibliothèques, de fichiers de configuration. Monter à 4 096 Ko avec un TTL d'une heure en production stable évite les recalculs constants.
Pour vérifier que le cache est plein et déborde, realpath_cache_size() retourne la taille utilisée. Si elle est proche du plafond, augmenter.
Préchargement PHP 8 : principe et configuration
Le préchargement charge des fichiers PHP au démarrage de PHP-FPM et les garde en mémoire partagée pour toutes les requêtes, sans compilation et sans lecture de fichier. Le gain est maximal pour les classes utilisées dans chaque requête Drupal.
opcache.preload=/var/www/html/preload.php
opcache.preload_user=www-data
Drupal ne fournit pas de script de préchargement par défaut. Un script minimal charge les composants du noyau les plus sollicités. La liste doit être construite à partir des profils de requêtes réelles (Xdebug, Blackfire) plutôt que d'une intuition. Précharger des classes rarement utilisées consomme de la mémoire partagée sans retour.
Effets de bord à surveiller
Déploiements avec validate_timestamps=0
PHP ne voit pas les nouveaux fichiers. Le déploiement doit inclure un reset d'OPcache. Deux options :
- Reload de PHP-FPM : vide tout le cache, quelques millisecondes de downtime possible. Obligatoire après chaque déploiement qui touche des classes préchargées.
- Reset programmatique via
opcache_reset()appelé depuis un endpoint dédié dans le pipeline de déploiement.
Un pipeline de déploiement sans cette étape sert du code périmé jusqu'au prochain redémarrage. C'est la cause la plus fréquente de déploiements Drupal qui « ne se voient pas ».
CLI et workers
opcache.enable_cli=0 est délibérément recommandé ci-dessus. Les scripts Drush, les migrations et les workers de files (drush queue:run) tournent en processus séparés qui ne partagent pas le cache de PHP-FPM. Activer OPcache en CLI consomme de la mémoire pour des processus éphémères sans gain significatif.
Pour les workers de longue durée, OPcache ne se rechargera pas automatiquement. Un worker lancé avant un déploiement peut exécuter du bytecode obsolète. La stratégie standard : arrêter les workers avant le déploiement, relancer après le reload de PHP-FPM.
Check-list d'observabilité pour valider les gains
Avant de passer en production, valider que les paramètres sont réellement appliqués et que le cache fonctionne.
Vérifier qu'OPcache est actif et correctement dimensionné
$status = opcache_get_status(false);
echo 'Hit rate : ' . $status['opcache_statistics']['opcache_hit_rate'] . '%';
echo 'Mémoire utilisée : ' . $status['memory_usage']['used_memory'];
echo 'Scripts en cache : ' . $status['opcache_statistics']['num_cached_scripts'];
- Hit rate en production : viser 99 % ou plus. Un hit rate sous 95 % signale que
max_accelerated_filesest trop bas ou que la mémoire est insuffisante. - Si
used_memoryest proche dememory_consumption, augmenter la valeur.
Vérifier le realpath cache
Appeler realpath_cache_size() et comparer avec la valeur déclarée dans php.ini. Si la valeur dépasse 90 % du plafond, augmenter la taille.
Après déploiement
Modifier temporairement une chaîne visible en front, déployer, recharger. Si la chaîne n'apparaît pas, le reset n'a pas fonctionné.
Surveillance continue
Exposer opcache_get_status() vers un outil de monitoring (Prometheus, Datadog, Grafana) pour suivre le hit rate et l'utilisation mémoire dans la durée. Une dégradation du hit rate après un déploiement ou une montée en charge est un signal d'alerte.
Ce que ces réglages ne font pas
OPcache, le préchargement et le realpath cache réduisent le coût CPU et I/O du bootstrap PHP. Ils ne remplacent pas :
- le cache applicatif de Drupal (cache render, page cache, dynamic page cache) ;
- un reverse proxy ou un CDN pour les assets statiques ;
- un profiling des requêtes lentes (Blackfire, Xdebug Profiler) pour identifier les vraies causes d'une lenteur.
Les réglages PHP sont la fondation. La superstructure, c'est le reste de la stack.