Accélérez l'exécution des fichiers PHP avec OPcache et JIT
Pour exécuter un fichier PHP, plusieurs environnements sont couramment utilisés, notamment :
- Apache avec mod_php : intègre PHP directement dans le serveur web Apache.
- PHP-FPM (FastCGI Process Manager) : utilisé avec des serveurs web comme Nginx pour gérer les requêtes PHP.
- PHP-CLI (Command Line Interface) : permet d'exécuter des scripts PHP directement depuis la ligne de commande.
Quel que soit l'environnement choisi, l'exécution du code PHP repose sur le moteur Zend Engine, qui réalise plusieurs étapes cruciales :
- Validation de la syntaxe : vérifie que le code PHP est correctement écrit.
- Pré-compilation : traduit le code PHP en une série d'instructions appelées "opcodes".
- Exécution : les opcodes sont interprétés et exécutés par la machine virtuelle Zend, qui s'interface avec le processeur physique.
Fonctionnement de la machine virtuelle Zend
À l'intérieur de la machine virtuelle Zend, un processus virtuel tourne en continu pour exécuter les instructions (opcodes) qu'il reçoit. La VM utilise une mémoire virtuelle pour stocker les données et les résultats des calculs.
Cependant, certaines fonctions comme file_get_contents
ou des fonctions de manipulation d'images ne sont pas directement écrites en PHP. Ces fonctions font appel à des extensions écrites en C, comme GD pour le traitement d'images.
Pourquoi utiliser la machine virtuelle Zend ?
La VM Zend apporte deux avantages principaux :
- Performance : La VM Zend transforme les instructions en une forme simplifiée avec un nombre limité d'opérandes (maximum trois). Cela permet au code d'être exécuté plus efficacement par le processeur, contrairement aux fonctions PHP qui peuvent avoir un nombre indéfini de paramètres.
- Abstraction : La VM fournit une couche d'abstraction qui permet aux développeurs de PHP de se concentrer sur la logique du langage sans se soucier des différences de plateformes. Ils n'ont qu'à s'assurer que le code fonctionne sur la VM, tandis que d'autres équipes s'occupent de la compatibilité de la VM avec différents systèmes d'exploitation.
Comprendre les OpCodes
Les instructions générées par la compilation du code PHP sont organisées sous forme d'un oparray (tableau d'opérations). Chaque élément de ce tableau est une opline (ligne d'opération), qui peut ressembler à ceci :
0x02 0x0A 0x05
Chaque ligne est composée de :
- Opcode : la première valeur (par exemple,
0x02
), représentant l'opération à effectuer. - Operands : les paramètres de l'opcode (par exemple,
0x0A
et0x05
).
Par exemple, l'opline 0x02 0x0A 0x05
pourrait se traduire par ADD 10 5
, signifiant qu'en PHP, une instruction comme 10 + 5
est représentée sous cette forme simplifiée dans la VM Zend.
Qu'est-ce que l'OPcache ?
Dans le processus d'exécution du Zend Engine, environ 80 % du temps est consacré à la validation de la syntaxe et à la pré-compilation, tandis que seulement 20 % est consacré à l'exécution. OPcache est un mécanisme de cache qui vise à réduire ce temps de compilation en stockant les opcodes en mémoire.
Lorsque le code PHP est pré-compilé, les opcodes sont mis en cache par OPcache. Si le fichier PHP n'a pas changé, ces opcodes sont réutilisés directement lors de la prochaine exécution, sans recompilation, ce qui accélère considérablement l'exécution.
Configuration d'OPcache
Les paramètres d'OPcache peuvent être configurés via le fichier .ini
du serveur web. Voici quelques options essentielles :
opcache.enable=1 |
Active l'OPcache. |
opcache.memory_consumption=256 |
Définit la taille de mémoire allouée (en Mo). |
opcache.max_accelerated_files=20000 |
Nombre de fichiers pouvant être mis en cache (valeur minimale : 2000, maximale : 1 000 000). |
opcache.validate_timestamps=1 |
Active la revalidation du cache basée sur le timestamp des fichiers. |
opcache.revalidate_freq=2 |
Fréquence (en secondes) de vérification du timestamp pour déterminer si le cache doit être revalidé. |
En production, il est conseillé de désactiver la validation automatique du cache en définissant opcache.validate_timestamps=0
, puis de gérer manuellement la purge du cache après chaque déploiement en utilisant la fonction opcache_reset()
.
Qu'est-ce que le JIT (Just-In-Time Compilation) ?
Traditionnellement, les instructions opcode générées par la compilation du code PHP sont exécutées au sein de la machine virtuelle Zend, qui fonctionne comme une couche d'abstraction au-dessus du processeur physique. Le concept du JIT, introduit avec PHP 8, vise à améliorer les performances en transformant directement ces instructions opcode en code machine exécutable par le processeur physique.
Le JIT ajoute une nouvelle étape dans le processus d'exécution : il génère du code assembleur à partir des opcodes, permettant au code PHP compilé de s'exécuter directement sur le processeur, sans passer par la Zend VM. Cela réduit le temps d'exécution en éliminant l'interprétation des opcodes dans la machine virtuelle, ce qui peut considérablement accélérer les performances du code.
Quand le JIT est-il utile ?
Le JIT est particulièrement bénéfique pour les tâches intensives en calcul, telles que les algorithmes mathématiques complexes, le traitement d'images, ou toute autre opération nécessitant de nombreuses ressources de calcul. Dans ces cas, la conversion directe en code machine permet de tirer parti des performances maximales du processeur.
En revanche, pour les applications principalement orientées vers les accès à la base de données, les appels réseau ou les opérations I/O, les avantages du JIT sont plus limités. Dans ces situations, le temps d'exécution est souvent dominé par les latences réseau ou les temps d'accès aux données, rendant les optimisations du JIT moins significatives.
Combinaison de OPcache et JIT
Le JIT et OPcache peuvent être utilisés ensemble pour des gains de performance optimaux. OPcache stocke les opcodes compilés en mémoire, réduisant ainsi le temps nécessaire à la compilation des scripts PHP, tandis que le JIT convertit ces opcodes en code machine pour une exécution directe sur le processeur.
Cependant, il est important de noter que ces deux technologies ont des implications différentes sur les ressources système. OPcache augmente la consommation de mémoire pour stocker les opcodes mis en cache, alors que le JIT introduit une surcharge supplémentaire de la CPU en raison de la traduction dynamique du code. Le choix d'utiliser JIT et OPcache dépendra donc du type de charge de travail et des ressources disponibles sur votre serveur.