Performance PHP LiteSpeed : optimiser LSAPI, cache opcode et concurrence

Optimiser PHP sous LiteSpeed pour PrestaShop : calibrage LSAPI, OPcache adapté et gestion de la concurrence (sessions, MySQL, I/O) pour réduire le TTFB et stabiliser la charge.

Écrans d'ordinateur affichant des codes et graphiques pour l'optimisation serveur.

Table des matières :

  1. LSWS/OLS + LSAPI : ce que ça change vraiment par rapport à PHP‑FPM
  2. Calibrer LSAPI : children, maxConns, timeouts et recyclage des process
  3. Cache opcode (OPcache) : sizing, invalidation, preload… et pourquoi le JIT est rarement le levier
  4. Concurrence réelle : sessions, MySQL, I/O disque et effets de bord PrestaShop
  5. Mesurer et monitorer : bench, métriques OPcache, saturation CPU et SLO
  6. Checklist « Performance PHP LiteSpeed » (LSAPI + OPcache + concurrence) utilisable en production

LSWS/OLS + LSAPI : ce que ça change vraiment par rapport à PHP‑FPM

La performance PHP sous LiteSpeed se joue sur un triptyque très concret : (1) le modèle d’exécution LSAPI (process manager), (2) le cache opcode (OPcache) et (3) la concurrence réelle de la stack (PHP + MySQL + I/O + sessions). Sur un PrestaShop moderne (8.1/8.2/9.x) en PHP 8.2 ou 8.3, LiteSpeed Web Server (LSWS) et OpenLiteSpeed (OLS) peuvent réduire la latence (TTFB) et augmenter le débit… mais uniquement si vous calibrez LSAPI et OPcache. Par défaut, beaucoup d’installations tournent avec des valeurs « safe » qui deviennent vite des plafonds.

Définition opérationnelle : LSAPI est une SAPI PHP (Server API) spécifique à LiteSpeed, comparable à FastCGI/PHP‑FPM côté rôle (un serveur HTTP parle à un pool de processus PHP), mais avec sa propre implémentation et ses propres variables d’environnement. Là où PHP‑FPM gère un pool via pm.*, LSAPI pilote des children via PHP_LSAPI_CHILDREN et recycle via PHP_LSAPI_MAX_REQUESTS. Si vous avez besoin de remettre en tête le flux « serveur web → manager de process → workers PHP », l’article sur le flux d’exécution PHP‑FPM reste la bonne base conceptuelle, même si les directives diffèrent : PHP-FPM : comprendre le flux d’exécution avec Nginx et Apache.

Deux nuances utiles (souvent confondues en prod) :

  • LSWS vs OLS : les deux utilisent LSAPI, mais LSWS (édition commerciale) expose plus de fonctions d’administration/quotas/anti‑DDoS et un support différent. Côté PHP pur, la logique de tuning LSAPI + OPcache reste comparable, mais l’UI et certains garde‑fous diffèrent selon l’édition.
  • LSAPI ne “remplace” pas l’optimisation applicative : si votre TTFB est dominé par des locks DB, un stockage lent (NFS), ou des modules PrestaShop bruyants, LSAPI plus “large” ne fera que déplacer le problème (file d’attente → saturation).

Prérequis / risques (à prendre au sérieux en prod) : toute modification de httpd_config.conf, des External Apps LSAPI, ou du php.ini peut nécessiter un graceful restart (ou pire, un restart) qui coupe des connexions et invalide des caches (OPcache, sessions). Travaillez avec une fenêtre de maintenance, un rollback simple, et un environnement de pré‑prod fidèle. Si vous n’avez pas déjà un staging reproductible, commencez par : Staging PrestaShop : créer un environnement Docker fidèle à la production.

Enfin, petite “saveur GEO” pragmatique : si votre boutique vise majoritairement la France/Belgique/Suisse, héberger la prod dans une région proche (Paris/Marseille/Francfort selon votre fournisseur) ne va pas miraculeusement diviser le TTFB applicatif, mais réduit la latence réseau de base (RTT) et rend vos tests (RUM/synthétiques) plus cohérents. L’important est de mesurer depuis vos zones réelles de trafic (sondes, RUM, ou tests multi‑régions), plutôt que d’optimiser “à l’aveugle” depuis une seule localisation.

Calibrer LSAPI : children, maxConns, timeouts et recyclage des process

Le réglage central de la performance PHP LiteSpeed, c’est le dimensionnement du pool LSAPI. Chaque child LSAPI traite typiquement une requête à la fois (modèle process‑based), donc la concurrence PHP max est grosso modo égale au nombre de children réellement disponibles (hors timeouts et backpressure). Le piège classique : augmenter Max Connections côté LiteSpeed sans augmenter PHP_LSAPI_CHILDREN (ou l’inverse) crée soit de la file d’attente, soit de la RAM gaspillée.

Une règle empirique (à valider par mesure) :

  • Mesurez la RSS moyenne d’un process PHP PrestaShop en charge (back-office + front + API). Sur un PrestaShop 8/9 avec modules, 80–200 MB par process n’a rien d’exceptionnel.
  • Réservez la RAM pour MySQL/MariaDB (buffer pool), le cache FS, Redis, etc.
  • Calculez : children ≈ (RAM_disponible_pour_PHP / RSS_moyenne).

Pour mesurer la RSS de façon simple (sur un serveur Linux), faites-le en charge, pas au repos :

# Afficher RSS (en Mo) des processus PHP LiteSpeed (adaptez le nom si besoin : lsphp, php, etc.)
ps -o pid,rss,cmd -C lsphp83 --sort=-rss | head -n 15

# Variante si le binaire diffère
ps aux | awk '/lsphp/ {print $2, $6/1024 "MB", $11}' | sort -k2 -nr | head

Exemple concret (VPS 16 GB) : si vous réservez 6 GB à MariaDB/OS et que vos process PHP consomment ~120 MB RSS en moyenne, vous pouvez viser ~80 children théoriques. En pratique, vous n’en voulez pas 80 si vous n’avez que 8 vCPU : vous allez créer du CPU contention (run queue) et dégrader les p95/p99. Sur 8 vCPU, un point de départ réaliste est souvent 16 à 32 children, puis ajustement par tests de charge.

Un repère de démarrage (à valider au benchmark) qui évite les extrêmes :

Profil serveur Démarrage LSAPI (children/maxConns) Intention
2 vCPU / 4–8 GB RAM 6–10 Éviter la saturation CPU, garder de la RAM pour DB
4 vCPU / 8–16 GB RAM 12–20 Confort “petite boutique” + BO
8 vCPU / 16–32 GB RAM 16–32 Bon compromis pour pics + tâches BO
16 vCPU / 32–64 GB RAM 32–64 Utile si DB/I/O suivent (sinon ça casse ailleurs)

Configuration LSAPI (illustrative, la UI LiteSpeed WebAdmin est souvent la voie la plus simple). Dans LSWS, l’external app ressemble à ceci (syntaxe proche, selon version) :

extprocessor lsphp {
  type                    lsapi
  address                 uds://tmp/lshttpd/lsphp.sock
  maxConns                32
  env                     PHP_LSAPI_CHILDREN=32
  env                     PHP_LSAPI_MAX_REQUESTS=5000
  env                     LSAPI_AVOID_FORK=2000
  initTimeout             60
  retryTimeout            0
  respBuffer              0
  autoStart               1
  path                    /usr/local/lsws/lsphp83/bin/lsphp
}

Points à comprendre (sinon vous itérez au hasard) :

1) maxConns doit être cohérent avec PHP_LSAPI_CHILDREN. Si maxConns < children, vous bridez artificiellement. Si maxConns > children, vous créez un goulot d’étranglement côté LSAPI (beaucoup de connexions en attente) et vous masquez le problème.

2) PHP_LSAPI_MAX_REQUESTS recycle les process après N requêtes. C’est un garde‑fou contre les fuites mémoire de certains modules/extends (ou d’extensions PHP). Trop bas = surcoût de respawn ; trop haut = dérive RAM possible. 3000–10000 est un ordre de grandeur courant.

3) Les timeouts (initTimeout, Connection Timeout, etc.) doivent être alignés sur les timeouts upstream (CDN, LB, HAProxy). Sinon vous fabriquez des erreurs 499/504 difficiles à corréler. Si vous avez HAProxy devant, gardez une cohérence globale (voir : HAProxy : configuration avancée ACL, health checks et sticky sessions).

Ajoutez deux garde‑fous “systèmes” (souvent oubliés) :

  • File descriptors : si vous poussez la concurrence, vérifiez ulimit -n et les limites systemd (sinon vous obtenez des erreurs intermittentes difficiles à diagnostiquer : sockets, fichiers, logs).
  • Plafond DB : si children = 64 et que chaque requête ouvre 1 connexion DB, votre max_connections côté MySQL/MariaDB et la capacité réelle de la DB deviennent le plafond. Une montée en concurrence PHP sans budget DB = timeouts/locks.

Cache opcode (OPcache) : sizing, invalidation, preload… et pourquoi le JIT est rarement le levier

OPcache n’a rien d’optionnel sur une boutique qui encaisse du trafic. Le PHP Manual résume le rôle sans ambiguïté : « OPcache improves PHP performance by storing precompiled script bytecode in shared memory » (PHP Manual, OPcache : PHP Manual — OPcache). Le point clé : sans OPcache correctement dimensionné, vous repassez du temps CPU à parser + compiler des milliers de fichiers, exactement ce que PrestaShop (core + vendor + modules) fait le plus.

Vous avez déjà une base de paramètres recommandés ? Ne réinventez pas tout, mais relisez avec une grille « LiteSpeed + PrestaShop » : PHP OPcache : paramètres recommandés pour optimiser les performances. Ce qui change souvent en pratique sur PrestaShop : opcache.max_accelerated_files est trop faible (le cœur + vendor + modules explose rapidement 10k fichiers) et opcache.memory_consumption sous-dimensionné (128 MB est fréquemment trop court).

Un profil de départ robuste (PHP 8.2/8.3, prod, déploiements maîtrisés) ressemble à :

; OPcache
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=40000
opcache.max_wasted_percentage=10

; Stratégie d'invalidation (prod)
opcache.validate_timestamps=0
opcache.revalidate_freq=0

; Filesystem / stat
realpath_cache_size=4096K
realpath_cache_ttl=600

Trois points “terrain” qui aident à éviter les faux gains :

  • Visez l’absence de redémarrages OPcache en charge : si OPcache “restart” parce que la mémoire est pleine/fragmentée, vous perdez une partie du bénéfice (et vous créez des pics CPU). Surveillez opcache_get_status() (ou l’équivalent exposé par votre stack de métriques) et cherchez : used memory, free memory, wasted memory, num cached scripts, oom restarts, hash restarts.
  • opcache.max_accelerated_files : trop bas, vous “thrash” (cache qui évince en permanence). Trop haut n’est pas grave en soi, mais augmente un peu la taille des tables de hachage ; le vrai risque est surtout d’oublier d’augmenter memory_consumption en conséquence.
  • realpath_cache_* : sur des projets avec beaucoup d’includes/autoload (Composer), ce cache réduit des stat() répétitifs. C’est un micro-levier, mais souvent “gratuit”.

Le choix opcache.validate_timestamps=0 est agressif mais pertinent si (et seulement si) vous avez un process de déploiement qui fait un reload des workers (ou un touch ciblé + opcache_reset() via endpoint admin protégé, ce qui est rarement propre). Sans ça, vous allez servir du code obsolète. Dans un contexte CI/CD sérieux, coupez la validation et gérez l’invalidation au déploiement.

Pour un scénario concret côté e‑commerce : si vous déployez 2 à 5 fois/semaine (modules, overrides, thème), validate_timestamps=1 peut être un compromis acceptable le temps de fiabiliser votre pipeline. Une fois le déploiement “propre” (build immuable + restart maîtrisé + warming), passer à 0 devient logique.

À propos du preloading (opcache.preload) : ça peut aider si vous avez un set stable de classes critiques (autoloader Composer + classes PrestaShop/Symfony). Mais sur PrestaShop, la variabilité des modules et overrides rend le preload fragile (et les erreurs de preload cassent le démarrage des workers). Si vous voulez pousser ce levier, faites-le sur une branche qui gèle les modules, et testez froid/chaud (reboot, restart LiteSpeed, montée en charge).

Concernant le JIT : sur des workloads e‑commerce typiques (beaucoup d’I/O, de DB, de templates, de JSON, peu de calcul pur), le JIT est rarement le facteur limitant. Activez-le uniquement si vous avez un cas mesuré (p.ex. génération d’images/PDF en masse). Sinon, vous ajoutez de la complexité et parfois de l’instabilité pour un gain quasi nul.

Concurrence réelle : sessions, MySQL, I/O disque et effets de bord PrestaShop

Augmenter les children LSAPI ne suffit pas si l’application sérialise déjà ses requêtes. Exemple trivial : verrouillage de session. Par défaut, les sessions fichiers peuvent verrouiller et séquencer des requêtes concurrentes pour le même utilisateur, notamment côté back-office (multi-onglets, requêtes AJAX). Si vous avez des symptômes du type « une action BO bloque toutes les autres », regardez session.save_handler et la latence I/O sur le répertoire de session. Passer à Redis (sessions) peut réduire la contention et déplacer le problème sur le réseau (à surveiller), mais c’est souvent plus stable que le filesystem sur du stockage réseau.

Mini-scenario typique : en BO, un employé ouvre 3 onglets (commande, produit, module) + des appels AJAX (autocomplétion, stats). Si la session verrouille et que le FS de session est lent (disque partagé, I/O wait), vous observez des “pauses” qui ressemblent à un problème CPU… alors que le serveur est en attente. Dans ce cas, augmenter LSAPI augmente juste le nombre de requêtes bloquées.

Deuxième goulot : la base. En e‑commerce, la plupart des temps de réponse p95 se jouent dans MySQL/MariaDB (requêtes non indexées, N+1, locks InnoDB) avant même d’arriver au CPU PHP. Si vous augmentez la concurrence PHP sans contrôler la concurrence DB, vous passez d’un serveur « lent » à un serveur « instable » (locks, saturation, timeouts). Travaillez avec les outils de base : slow query log, EXPLAIN, indexation. Référence directe : PrestaShop MySQL : analyser slow query log et optimiser index.

Point pratique : alignez votre budget de connexions DB sur votre tuning LSAPI. Exemple : si votre MariaDB a max_connections=200, que vous voulez garder de la marge (réplication, admin, tâches cron), et que votre trafic réel n’a jamais besoin de plus de 40 requêtes PHP simultanées, dimensionner LSAPI à 80 ne donne pas un meilleur TTFB — ça augmente juste le risque de pics et de “thundering herd”.

Troisième point : l’I/O disque et le cache applicatif. PrestaShop écrit beaucoup plus que ce qu’on croit (cache Smarty, logs, sessions, fichiers temporaires, images en régénération). Si votre FS est lent (ou monté via NFS), augmenter LSAPI amplifie la pression I/O et fait exploser la latence. Avant de toucher à LSAPI, verrouillez les basiques côté PrestaShop : cache Smarty, CCC, CDN (pour éviter de servir des assets depuis PHP), et règles de compilation. Article connexe : PrestaShop : optimiser performance via cache Smarty, CCC et CDN.

Enfin, ne confondez pas les niveaux de cache : OPcache accélère l’exécution PHP (opcode) ; LSCache (côté LiteSpeed) est un cache HTTP de pages/objets. LiteSpeed Cache est très documenté côté optimisation front (images, lazy-loading), mais sur PrestaShop l’intégration de cache de page complet est plus délicate (cookies, panier, prix, groupes, B2B). Pour l’aspect front, utile en complément : LiteSpeed Cache : lazy‑loading, LQIP et VPI pour optimiser les images.

Pour éviter les effets de bord, un réflexe simple : quand vous augmentez la concurrence PHP, vérifiez aussi ce qui devient concurrent derrière (tables MySQL, filesystem, Redis, APIs). Le “bon” réglage est celui qui garde des p95/p99 stables, pas celui qui maximise le RPS sur une page facile.

Mesurer et monitorer : bench, métriques OPcache, saturation CPU et SLO

Sans mesures, vous allez « optimiser » des paramètres qui ne sont pas le bottleneck. En pratique : définissez un SLO (objectif de service) lisible, puis testez et itérez.

Exemples de SLO réalistes (à adapter à votre business et votre géographie) :

  • Front (France/Europe) : TTFB p95 < 400–600 ms sur pages catalogue (hors cache full page), erreurs 5xx < 0,1%.
  • BO : actions critiques (ouvrir commande, sauvegarder produit) p95 < 1,5–2 s.
  • Stabilité : pas de pics d’erreurs lors des pics (campagnes, soldes), pas de restarts OPcache en charge.

Pour l’impact utilisateur et SEO, surveillez particulièrement le TTFB et la stabilité des p95/p99 (qui finissent par se refléter dans l’expérience, et indirectement dans vos signaux web). Si vous cherchez une grille technique orientée SEO/perf : SEO PrestaShop : checklist technique 2025 pour indexation et performance.

Méthodo simple (et efficace) :

1) Choisissez 3 endpoints représentatifs : page catégorie (facettes), page produit (prix/stock), panier/checkout (si accessible). En BO, testez une page lourde (commande, catalog).
2) Faites un warm-up (cache FS, OPcache, cache application).
3) Lancez un test de charge avec wrk ou k6 en contrôlant le RPS et la concurrence (connections). Mesurez p50/p95/p99 et le taux d’erreur.

Deux conseils qui rendent vos benches beaucoup plus exploitables :

  • Stabilisez les données : même catalogue, même volumétrie, mêmes modules activés. Une régénération d’images ou une indexation en tâche de fond peut ruiner un test.
  • Isolez les variables : changez un seul paramètre à la fois (ex. children 16 → 24) et gardez la même charge (mêmes VUs, même durée).

Côté monitoring, vous voulez voir la saturation avant le crash : CPU steal (VM), run queue, memory pressure, I/O wait, connexions DB, et surtout la santé OPcache (hit rate, memory used, restarts). Netdata est très pratique pour une vue temps réel rapide : Netdata : activer et configurer les collectors pour monitoring temps réel. Si vous êtes déjà sur Prometheus, formalisez des alertes : saturation CPU, php_opcache_restarts_total, latence DB, erreurs 5xx (voir : Prometheus : configuration des alertes, métriques et requêtes PromQL).

Côté LiteSpeed, exploitez les stats serveur (connexions, busy workers, throttling) et corrélez avec les métriques PHP. Un signal simple : si la latence augmente alors que le CPU reste moyen, vous êtes souvent sur un lock (DB, session, FS). À l’inverse, CPU à 100% + p99 qui explose = trop de concurrence PHP par rapport aux vCPU, ou un endpoint CPU-bound (rare sur PrestaShop, mais possible via certains modules).

Pour accélérer le diagnostic, une grille “symptôme → cause probable” :

Symptôme observé Cause probable Ajustement prioritaire
p95/p99 augmentent, CPU moyen, I/O wait monte FS lent (sessions/cache/logs), NFS Déplacer sessions/cache, réduire writes, optimiser stockage
CPU 100%, erreurs 503/504, run queue élevée Trop de children vs vCPU, endpoint lourd Baisser children, profiler endpoint, limiter concurrence
MySQL saturé, locks, timeouts Concurrence PHP trop élevée vs DB Index/slowlog, réduire children, pool DB, cache applicatif
OPcache “restarts”, CPU en dents de scie OPcache sous-dimensionné/fragmenté Augmenter memory_consumption, ajuster max_accelerated_files

Checklist « Performance PHP LiteSpeed » (LSAPI + OPcache + concurrence) utilisable en production

Avant de toucher aux réglages, verrouillez le contexte : version PHP (8.2/8.3), version PrestaShop (8.x/9.x), et modèle d’hébergement (mutualisé / VPS / dédié). Sur du mutualisé LiteSpeed, vous n’aurez pas toujours accès aux paramètres LSAPI fins ; dans ce cas, l’optimisation passe surtout par OPcache (si exposé), la réduction des modules, et le cache applicatif. Si vous êtes en phase de choix d’infra, les critères sont explicités ici : Hébergement PrestaShop : mutualisé, VPS ou cloud managé, comment choisir.

Checklist opérationnelle (ordre conseillé) :

  • Vérifier la SAPI : un phpinfo() doit afficher Server API => LiteSpeed (sinon vous n’êtes pas en LSAPI).
  • Dimensionner LSAPI : ajuster PHP_LSAPI_CHILDREN et maxConns sur une cible (ex. 16/32) puis tester en charge.
  • Recyclage : fixer PHP_LSAPI_MAX_REQUESTS (ex. 5000) pour éviter les dérives mémoire.
  • OPcache : pousser memory_consumption (256/512), max_accelerated_files (20k–60k), surveiller le hit rate et les restarts.
  • Invalidation : en prod, décider (et documenter) entre validate_timestamps=1 (simple, moins performant) et =0 (performant, déploiement strict obligatoire).
  • I/O & cache PrestaShop : activer cache Smarty/CCC proprement, et éviter que PHP serve des assets.
  • DB : slow query log, index, et capacité de connexions (sinon LSAPI « DoS » MySQL).

Trois garde-fous souvent oubliés :

1) Limiter la concurrence côté crawler / bots : LiteSpeed peut absorber, mais PrestaShop et MySQL, beaucoup moins. Si votre crawl explose, vous allez fausser vos benchmarks.

2) Stabilité avant performance : un réglage qui gagne 10% sur p50 mais fait exploser p99 et le taux d’erreur est un mauvais réglage. Pour un e‑commerce, les erreurs coûtent plus que la moyenne.

3) Documenter la config : LiteSpeed/LSAPI est moins standardisé que Nginx+FPM, donc sans runbook vous perdez votre tuning à la prochaine maintenance, migration ou montée de version PHP.

En pratique, si vous appliquez (a) un LSAPI correctement dimensionné, (b) un OPcache dimensionné et maîtrisé au déploiement, et (c) une concurrence alignée avec la DB et l’I/O, vous obtenez généralement une baisse visible du TTFB et une meilleure tenue en charge, sans « magie » et sans dépendre d’un cache page complet difficile à rendre correct sur PrestaShop.


À lire aussi