...

Détecter et corriger la fragmentation de l'Opcache PHP pour optimiser les performances

La fragmentation de l'OPcache ralentit sensiblement les applications PHP, car le cache divise la mémoire libre en petits îlots, ce qui réduit sa capacité à accueillir de nouveaux blocs de bytecode. Je vais te montrer comment Fragmentation les identifie avec certitude, les élimine de manière ciblée et les empêche durablement grâce à des déploiements propres et à une configuration adaptée de l'OPcache.

Points centraux

Les points clés suivants te fournissent un plan d'action rapide que tu peux mettre en œuvre étape par étape et ainsi Performance stabilises.

  • Chiffres clés lire : used/free/wasted_memory, current_wasted_percentage, opcache_hit_rate.
  • Seuils Condition : wasted_memory < 5 % (bon) ; à partir de 15–30, agir selon %.
  • Configuration augmenter : memory_consumption, max_accelerated_files, interned_strings_buffer.
  • Réinitialiser- Stratégie : appel planifié de la fonction opcache_reset() ou redémarrage du service avec phase de préchauffage.
  • Déployer-Discipline : chemins stables, invalidation contrôlée, surveillance.

Pourquoi la fragmentation d'OPcache se produit-elle ?

OPcache stocke le bytecode compilé dans le Partagé Mémoire : cependant, les déploiements fréquents, les changements de répertoires ou les nombreux changements de plugins laissent des espaces vides. Ces espaces ne peuvent pas être utilisés comme un bloc contigu, ce qui rend le cache inefficace et entraîne une recompilation plus fréquente du bytecode. Des intervalles de revalidation courts font grimper le nombre d’invalidations et aggravent le problème des blocs de mémoire fragmentés. Des limites trop basses pour la mémoire ou les index de fichiers augmentent les évictions et favorisent une disposition instable de la mémoire. Je commence par examiner les habitudes de déploiement et je privilégie des chemins d’accès constants, sinon la Fragmentation à chaque nouvelle version.

Comment interpréter correctement les indicateurs OPcache

J'analyse régulièrement les valeurs used_memory, free_memory et wasted_memory, car ces indicateurs reflètent la Cache-montrer la qualité. Le paramètre `current_wasted_percentage` est particulièrement important, car ce pourcentage peut facilement être associé à des seuils fixes. Si le `opcache_hit_rate` tombe sensiblement en dessous de 99 %, cette évolution indique un potentiel inexploité ou une fragmentation. Je surveille également « num_cached_scripts » afin de détecter si les limites imposées aux entrées de fichiers provoquent des goulots d'étranglement. Sans ces indicateurs, on avance à tâtons face à des fluctuations Performance dans le noir.

Seuils à partir desquels tu dois agir

Avec une valeur inférieure à 5 % wasted_memory, l'OPcache fonctionne généralement sans se faire remarquer et je laisse le Paramètres Pour l'instant. À partir de 15 %, je prévois des mesures correctives, en particulier si la mémoire libre (free_memory) vient à manquer en même temps. Au plus tard lorsque wasted_memory atteint 30 %, le cache est de fait considéré comme réduit, et je déclenche une réinitialisation ou un redémarrage. Si free_memory chute à environ 10 % et que le cache signale qu’il est plein, la fragmentation s’accélère. De telles limites facilitent la prise de décision, car elles Action au lieu de se fier à son intuition.

Interpréter correctement les symptômes en conditions réelles

Des augmentations régulières de la latence sur de nombreux terminaux indiquent un effet à grande échelle frein comme la fragmentation. Une charge CPU croissante pour un trafic identique correspond également à des recompilations plus fréquentes dues à un cache fragmenté. Un taux de réussite faible et persistant après la phase de préchauffage confirme en outre cette tendance. Si les redémarrages ou les évictions de l’OPcache se multiplient sans modifications majeures du code, cela signifie simplement que le cache manque d’espace dans les blocs contigus. J’associe ces indices aux métriques, puis je mets en œuvre des mesures ciblées Mesures de.

Surveiller et analyser OPcache de manière fiable

Un petit script utilisant opcache_get_status() me fournit les informations nécessaires Données directement depuis PHP. Pour des vérifications rapides, j'utilise phpinfo() ; pour les analyses de tendances, j'enregistre régulièrement les valeurs dans le système de surveillance. Je visualise les indicateurs wasted_memory, Hit-Rate et free_memory afin de détecter toute détérioration progressive. Des comparaisons chronologiques après chaque déploiement permettent de déterminer si certains schémas de mise en production accélèrent la fragmentation. Sans cet aperçu de l'historique, il est difficile d'en identifier les causes classer.

Configuration : définir clairement les limites de stockage et de taille des fichiers

Le paramètre `opcache.memory_consumption` me permet de définir la taille du Mémoire En fonction de la base de code : les petites installations WordPress fonctionnent souvent bien avec 128 à 256 Mo, les sites de taille moyenne avec 256 à 384 Mo, tandis que les boutiques en ligne plus importantes nécessitent 384 à 512 Mo, voire plus. Avec opcache.max_accelerated_files, j’évite qu’un nombre trop faible d’index de fichiers ne fasse baisser le taux de mise en cache ; des valeurs comprises entre 8 000 et 10 000 pour les petits sites WordPress, et 20 000 ou plus pour WooCommerce ou les grands frameworks ont fait leurs preuves. Je compte les fichiers PHP, y compris ceux des fournisseurs, et je fixe la limite à 1,3 à 1,5 fois ce nombre. Si vous souhaitez approfondir le sujet, vous trouverez des informations complémentaires sur la Configuration de l'OPcache dans un guide pratique. Des limites bien définies stabilisent la structure de la mémoire et réduisent la Fragmentation perceptible.

Utilisation des chaînes intégrées et des pages de codes volumineuses

Avec `opcache.interned_strings_buffer`, je réduis au minimum les doublons Chaînes en mémoire ; une capacité de 16 à 32 Mo permet aux projets de grande envergure d'utiliser l'espace de manière plus efficace. Ceux qui ont un trafic plus important tirent souvent profit de tampons encore un peu plus grands. En option, opcache.huge_code_pages accélère l’exécution, à condition que le système prenne en charge les grandes pages. Une charge administrative réduite se traduit généralement par des latences légèrement plus faibles et tend à limiter la fragmentation. Je n’active cette option qu’après des tests, afin d’éviter toute Surprises générées par l'exploitation.

Configurer correctement la validation et la revalidation des horodatages

Des vérifications trop strictes des horodatages invalident souvent le bytecode et entraînent la Fragmentation vers le haut. En environnement de développement, je maintiens `validate_timestamps=1` et `revalidate_freq` à un niveau bas afin que les modifications soient immédiatement visibles. En production, j’opte pour des intervalles modérés compris entre 60 et 300 secondes, ou je règle `validate_timestamps=0` et procède à une réinitialisation explicite de l’OPcache lors de la mise en production. Si vous souhaitez analyser les causes en profondeur, utilisez des analyses pour Validation de l'OPcache et les pics de performance éventuels. Grâce à l'invalidation contrôlée, la mémoire reste plus cohérente, le taux de réussite stable.

Éliminer la fragmentation de manière ciblée : stratégies de réinitialisation

Lorsque la mémoire gaspillée augmente sensiblement et que le taux de réussite baisse, je lance un Réinitialiser via opcache_reset() pendant les périodes de faible activité. Juste après, je lance un « warm-up » des routes importantes afin de remplir rapidement le cache et d’éviter les pics de charge. Sinon, je redémarre PHP-FPM ou Apache, ce qui renouvelle entièrement le segment de mémoire partagée. Après chaque réinitialisation, je surveille le taux de réussite (hit-rate), la mémoire gaspillée (wasted_memory) et la mémoire libre (free_memory) afin de m'assurer que le cache se rétablit comme prévu. Les redémarrages planifiés pendant la nuit s'avèrent efficaces pour les configurations qui Fragmentation mettre en place.

Prévention : déploiements et mises en route sans incident

Je déploie les versions dans de nouveaux répertoires et je les rends accessibles via un lien symbolique vers un fixe Je modifie le chemin d'accès, par exemple en le remplaçant par /var/www/html/current, afin qu'OPcache ne conserve pas d'anciennes données issues de chemins d'accès modifiés. Immédiatement après la bascule, j'effectue une réinitialisation contrôlée. Un script qui interroge les pages populaires, les routes REST et les pages de la boutique permet de précharger le cache de manière ciblée. Ainsi, le taux de réussite atteint rapidement un niveau élevé, et les utilisateurs ne remarquent pratiquement pas les fenêtres de maintenance. Grâce à cette rigueur, la Fragmentation permanent.

Conseils pratiques pour WordPress, WooCommerce et les frameworks

Les blogs WordPress comportant peu de plugins fonctionnent souvent avec une valeur de `memory_consumption` comprise entre 128 et 256 Mo, une valeur de `max_accelerated_files` d'au moins 8 000, ainsi qu'une valeur de `revalidate_freq` comprise entre 60 et 120 secondes. Les boutiques WooCommerce de plus grande envergure fonctionnent de manière plus fiable avec 256 à 512 Mo de mémoire, plus de 20 000 « max_accelerated_files » et un « interned_strings_buffer » de 16 à 32 Mo. Les frameworks tels que Laravel ou Symfony nécessitent souvent entre 20 000 et 40 000 index de fichiers et 256 à 512 Mo de mémoire, voire plus, en fonction de la taille du fournisseur. Pour éviter les écueils courants, vous trouverez un guide concis sur Erreurs de configuration d'OPcache dans les configurations WordPress. Le tableau suivant résume les options utiles Valeurs indicatives ensemble.

Type de projet memory_consumption max_accelerated_files revalidate_freq interned_strings_buffer
Petit WordPress 128 à 256 Mo 8 000–10 000 60 à 120 s 8 à 16 Mo
WooCommerce/Medium 256 à 384 Mo 20.000+ 60 à 180 s 16 à 32 Mo
Grande boutique en ligne / Multisite 384 à 512 Mo+ 30.000+ 120 à 300 s 32 à 48 Mo
Laravel/Symfony 256 à 512 Mo+ 20.000–40.000 60 à 180 s 16 à 32 Mo

Niveau avancé : préchargement et JIT sans effets secondaires

À partir de PHP 7.4, je peux utiliser `opcache.preload` pour charger les classes et fonctions fréquemment utilisées au démarrage. Cela réduit les temps de latence au démarrage à froid et stabilise le taux de réussite. Je tiens à souligner que le préchargement est étroitement lié au cycle de vie du processus PHP : si des fichiers préchargés sont modifiés, je prévois un redémarrage ciblé de PHP-FPM/Apache, car ces modifications ne prennent pas correctement effet uniquement via `opcache_reset()`. Dans PHP 8.x, il est également intéressant de se pencher sur le JIT : le paramètre opcache.jit_buffer_size réserve de la mémoire distincte pour la compilation JIT. Le JIT n’influence pas directement les métriques OPcache, mais peut améliorer la charge CPU et les temps de réponse. Lorsque le JIT est activé, je teste le temps de préchauffage et la marge de mémoire avec une attention particulière afin d’éviter toute pression supplémentaire sur le segment de mémoire partagée.

Comprendre le fonctionnement de l'allocateur : « free » vs « wasted »

OPcache gère la mémoire partagée par blocs. Lors de la suppression ou du remplacement de scripts, des espaces vides apparaissent, qui ne correspondent souvent pas exactement à la taille des nouveaux blocs de bytecode. Ces espaces vides sont considérés comme wasted_memory. free_memory En revanche, il s'agit d'un espace de stockage cohérent et exploitable de manière pertinente. Une part élevée de „ wasted “ alors qu'il semble y avoir « beaucoup d'espace libre » est le cas classique qui masque la capacité réelle. Je constate à quelle vitesse la mémoire perdue (wasted_memory) augmente après les déploiements : si ce taux explose dès les premières minutes, j’y vois le signe de chemins instables, d’intervalles de revalidation trop courts ou d’un code très changeant (par exemple, des fichiers de modèles régénérés fréquemment). Les « Huge Code Pages » réduisent la charge administrative et peuvent ainsi atténuer légèrement la tendance à la fragmentation, mais elles ne remplacent pas une stratégie de déploiement rigoureuse.

Déterminer les dimensions de manière méthodique : comment bien dimensionner

Au lieu de me contenter d'augmenter „ au feeling “, je procède de manière méthodique :

  • Je mesure les valeurs maximales de « used_memory » après un préchauffage complet et une charge journalière.
  • Je calcule la moyenne de la valeur « wasted_memory » pendant les phases stables (après une réinitialisation, avant les déploiements).
  • Je prévois une marge de 20 à 30 % pour les lancements, les pics saisonniers et la croissance.

À partir de ces éléments, on obtient une valeur cible pour opcache.memory_consumption. Pour opcache.max_accelerated_files, je compte tous les fichiers PHP (y compris ceux des fournisseurs) et je fixe la limite à 30 à 50 % au-dessus du nombre réel de fichiers, afin de compenser les fluctuations dues aux mises à jour. Une fois le réglage effectué, je vérifie si la valeur de `num_cached_scripts` reste durablement bien en dessous de la limite et si le taux de réussite se maintient de manière stable au-dessus de 99 % après la phase de préchauffage.

Guide de mise en route : atteindre rapidement et efficacement la température de fonctionnement

Un préchauffage permet d'éviter les pics liés au démarrage à froid et de répartir le bytecode de manière plus homogène. J'utilise deux niveaux :

  1. Préparation technique : je déclenche en parallèle les parcours principaux (Accueil, Connexion, Panier, Paiement, API de recherche).
  2. Préparation du contenu : je charge les pages et les points de terminaison REST les plus consultés à partir des journaux et des données analytiques.

Exemple de script « warmup » compact (Shell) :

#!/usr/bin/env bash
set -euo pipefail
BASE="https://example.org"
URLS=(
  "/" "/wp-login.php" "/shop/" "/cart/" "/checkout/"
  "/wp-json/wp/v2/posts?per_page=1" "/wp-json/wc/store/products?per_page=1"
)
for u in "${URLS[@]}"; do
  curl -fsS -m 10 -H "User-Agent: Warmup" "$BASE$u" &
done
wait

Pour des intégrations plus poussées, je peux également utiliser un point de terminaison PHP qui appelle la fonction `opcache_compile_file()` pour les fichiers fréquemment utilisés. Important : les scripts de préchauffage doivent être intégrés au pipeline de mise en production, juste après la réinitialisation et avant l'ouverture du trafic.

Variantes de déploiement : Blue/Green, Rolling, liens symboliques

Les déploiements « blue/green » avec un chemin de lien symbolique fixe permettent d’éviter les fluctuations de chemin. Dans le cadre de stratégies de déploiement progressif sur plusieurs serveurs d’applications, je synchronise rigoureusement les étapes : je commence par synchroniser le nouveau code, puis j’effectue une réinitialisation et un préchauffage pour chaque hôte, et enfin je bascule le trafic. Avec PHP-FPM, je fais la distinction entre « reload » et « restart » : un « reload » recharge les configurations, mais laisse souvent le segment de mémoire partagée existant continuer à fonctionner ; un Redémarrage Il recrée le segment et élimine la fragmentation de manière fiable. Sous Apache, avec PHP en tant que module, j'obtiens le même résultat en effectuant un redémarrage propre. Je documente clairement, pour chaque environnement, quelle commande vide „ réellement “ l'OPcache, afin de pouvoir continuer à planifier les fenêtres de maintenance nocturnes.

Cas particuliers : multi-tenant, CLI et worker

Dans les configurations multi-locataires, j'utilise des pools FPM distincts et je définis opcache.validate_permission=1 afin qu'un locataire n'utilise pas le code d'un autre. Cela renforce la sécurité et réduit les conflits de cache inattendus. Pour les tâches CLI, je vérifie la valeur de `opcache.enable_cli` : par défaut, cette option est désactivée, ce qui n’a pas d’incidence sur la fragmentation dans le chemin d’accès Web. Cependant, si j’utilise des workers CLI à exécution longue, il peut être judicieux d’activer l’OPcache CLI – dans ce cas, les mêmes règles s’appliquent pour la réinitialisation et la mise en condition. Pour les fichiers PHP générés dynamiquement ou changeant très fréquemment (par exemple, les artefacts de build, les sorties de modèles), je les mets sur liste noire avec `opcache.blacklist_filename` afin d’éviter le renouvellement et, par conséquent, la fragmentation.

Affiner la validation des fichiers et des chemins d'accès

La paramètre opcache.revalidate_path me permet de déterminer si OPcache effectue une nouvelle résolution lorsque les chemins include_path ou les liens symboliques sont modifiés. Dans les environnements de production stables, je laisse généralement cette valeur à 0. Si je passe d’une version à l’autre via un lien symbolique, je vérifie si l’application en dépend ; le cas échéant, j’active revalidate_path de manière ciblée. file_update_protection empêche les recompilations trop rapides juste après des modifications de fichiers (brève fenêtre de protection en secondes). Dans les pipelines de build qui remplacent les fichiers de manière atomique, je maintiens une valeur modérée afin que le code fraîchement déployé soit rapidement intégré au cache. L’option opcache.file_cache (cache de deuxième niveau sur disque) est utile pour accélérer la mise en route après un redémarrage ; elle ne remplace pas la gestion de la fragmentation dans la mémoire partagée, mais elle réduit les coûts de démarrage à froid et donc la fréquence des compilations précipitées.

Erreurs courantes et anti-modèles

  • „ Plus de mémoire résout tout “ : un cache trop volumineux, s'il n'est pas géré avec rigueur, finit par entraîner une fragmentation. Il faut d'abord définir une stratégie de déploiement et de réinitialisation.
  • „ Un rechargement suffit “ : dans de nombreux environnements, le segment de mémoire partagée persiste. Pour une véritable réinitialisation, je prévois un redémarrage ou l’appel à opcache_reset() suivi d’un « warmup ».
  • „ Un taux de réussite de 98 %, c'est quand même pas mal “ : en charge, 1 à 2 % supplémentaires entraînent des pics de latence perceptibles. L'objectif reste > 99 % après la mise en route.
  • „ Nous invalidons sans cesse – c'est plus sûr “ : les invalidations fréquentes accélèrent la fragmentation. Mieux vaut procéder à une invalidation contrôlée aux points de publication.

Dépannage : démarche structurée

  1. Enregistrer l'état : opcache_get_status(), used/free/wasted_memory, num_cached_scripts, opcache_hit_rate.
  2. Vérifier les limites : la valeur « wasted_memory » est-elle supérieure ou égale à 15 %, ou la valeur « free_memory » est-elle inférieure ou égale à 10 % ? Si oui, prévoir des mesures correctives.
  3. Vérifier les limites : max_accelerated_files par rapport au nombre réel de fichiers, interned_strings_buffer par rapport à l'utilisation des chaînes de caractères.
  4. Tester la combinaison « Reset + Warmup » : effectuer l'opération pendant une phase calme, comparer les indicateurs avant et après.
  5. Personnalisation des modèles de déploiement : chemins fixes, basculement des liens symboliques, invalidation uniquement lors de la mise en production.
  6. Renforcer la surveillance : observer les tendances sur plusieurs jours/semaines, établir des corrélations entre les pics et les déploiements.

Dans la pratique, un point de contrôle minimaliste pour la surveillance m'est d'une grande aide :

<?php
header('Content-Type: application/json');
echo json_encode(opcache_get_status(false));

En bref, pour la vie de tous les jours

Je maintiens wasted_memory en dessous de 5 %, le taux de réussite au-dessus de 99 % et free_memory bien en deçà de la limite des 10 %, car ces seuils constituent des repères clairs Signaux fournir. Si les valeurs atteignent des niveaux critiques, je prévois immédiatement une réinitialisation avec mise en route progressive ou j'augmente de manière judicieuse la taille de la mémoire et des index de fichiers. Les déploiements vers des chemins stables, associés à une invalidation contrôlée, empêchent les données obsolètes d'encombrer le cache. Une surveillance continue permet de détecter des tendances que de simples instantanés ne révèlent pas. Grâce à cette approche, la Performance de manière homogène et l'OPcache agit comme un accélérateur fiable plutôt que comme une source de risque.

Derniers articles

Serveur doté d'une mémoire PHP Opcache visualisée pour l'analyse de la fragmentation
Administration

Détecter et corriger la fragmentation de l'Opcache PHP pour optimiser les performances

Apprenez à détecter la fragmentation de l'OPcache PHP, à y remédier grâce à la surveillance et à la configuration, et à optimiser les performances de vos applications grâce à un réglage ciblé de PHP. Thème principal : la fragmentation de l'OPcache PHP dans les environnements d'hébergement professionnels.

Visualisation d'un cache Redis avec des serveurs et des flux de données illustrant les politiques d'éviction LFU et LRU
Bases de données

Redis LFU vs LRU : quelle politique d'éviction choisir ?

Pour configurer ton cache de manière optimale, tu dois comprendre comment fonctionne l'éviction Redis avec les algorithmes LFU et LRU de Redis : cet article te propose une comparaison directe et t'aide à choisir la stratégie la plus adaptée.