Maison >développement back-end >tutoriel php >Opcode PHP – Améliorez les performances des applications sans modifier votre code
L'opcode PHP généré par le moteur PHP est fortement influencé par la façon dont vous écrivez votre code. Pas seulement en termes de nombre d’instructions pour accomplir une tâche. C’est clair que c’est très important, et je pense que c’est évident pour vous.
Ce qui pourrait être moins évident, c'est que même la syntaxe du code peut changer complètement l'opcode généré, ce qui entraîne beaucoup de surcharge pour le processeur de la machine pour exécuter exactement le même code.
Au cours des dernières années, mon produit SaaS s'est beaucoup développé et cela m'a donné l'opportunité d'approfondir de plus en plus les techniques d'optimisation pour exécuter ma charge de travail aussi efficacement que possible.
Les résultats que j'ai constatés sont impressionnants et m'ont beaucoup aidé à débloquer des flux de trésorerie disponibles pour continuer à développer mon parcours SaaS.
À ce stade, le processus PHP à l'intérieur de mon produit SaaS traite plus de 1,2 milliard (avec B) de paquets de données chaque jour sur une machine dotée de 2 vCPU et de 8 Go de mémoire. J'utilise un groupe d'autoscaling AWS pour avoir plus de flexibilité en cas de pics imprévisibles, mais il ajoute rarement une deuxième machine (une à deux fois par semaine).
Pour des articles plus techniques vous pouvez me suivre sur Linkedin ou X.
Récemment, j'ai également écrit sur la migration des serveurs Inspector vers des instances ARM : https://inspector.dev/inspector-adoption-of-graviton-arm-instances-and-what-results-weve-seen/
Entrons dans le sujet de l'article. Je pense que vous le trouverez très intéressant.
PHP opcode signifie code d'opération et fait référence aux instructions de bas niveau qui sont exécutées par le moteur PHP après la compilation du code source PHP que vous écrivez.
En PHP, la compilation du code se produit au moment de l'exécution, essentiellement la première fois que votre code est pris par le moteur PHP, il sera compilé dans ce code convivial pour la machine, mis en cache, afin que le moteur ne compile plus le même code, et puis exécuté.
Voici une représentation simple du processus :
La mise en cache de l'opcode PHP vous permet d'enregistrer trois étapes dans le processus d'exécution du code : analyse du code PHP brut, tokenisation et compilation.
Une fois l'opcode généré pour la première fois, il est stocké en mémoire afin de pouvoir être réutilisé dans les requêtes ultérieures. Cela réduit la nécessité pour le moteur PHP de recompiler le même code PHP à chaque fois qu'il est exécuté, économisant ainsi beaucoup de consommation de CPU et de mémoire.
Le cache d'opcodes le plus couramment utilisé en PHP est OPCache, et il est inclus par défaut depuis PHP 5.5 jusqu'aux versions récentes. Il est très efficace et largement pris en charge.
La mise en cache du bytecode du script précompilé nécessite l'invalidation du cache après chaque déploiement. Parce que si les fichiers modifiés ont la version du bytecode dans le cache, PHP continuera à exécuter l'ancienne version du code. Jusqu'à ce que vous vidiez le cache des opcodes afin que le nouveau code soit à nouveau compilé générant un nouvel élément de cache.
Pour comprendre l'impact d'une syntaxe différente sur l'opcode du script, nous avons besoin d'un moyen de récupérer le code compilé généré par le moteur PHP.
Il existe deux façons d'obtenir l'opcode.
Si l'extension OPCache est activée sur votre machine, vous pouvez utiliser ses fonctions natives pour obtenir l'opcode d'un fichier php spécifique :
// Force compilation of a script opcache_compile_file(__DIR__.'/yourscript.php'); // Get OPcache status $status = opcache_get_status(); // Inspect the script's entry in the cache print_r($status['scripts'][__DIR__.'/yourscript.php']);
VLD est une extension PHP populaire qui désassemble le code PHP compilé et génère l'opcode. C'est un outil puissant pour comprendre comment PHP interprète et exécute votre code. Une fois installé, vous pouvez exécuter un script PHP avec VLD activé en utilisant la commande php avec les options -d :
php -d vld.active=1 -d vld.execute=0 yourscript.php
La sortie comprendra des informations détaillées sur l'opcode compilé, y compris chaque opération, sa ligne de code associée, et plus encore.
3v4l est un outil en ligne très utile qui vous permet de visualiser l'opcode généré par un code PHP que vous saisissez dans l'éditeur. Il s'agit essentiellement d'un serveur PHP sur lequel VLD est installé afin qu'il puisse récupérer la sortie VLD et vous montrer l'opcode dans le navigateur.
Comme il est distribué gratuitement, nous utiliserons cet outil en ligne pour les prochaines analyses.
3v4l est parfait pour comprendre comment la syntaxe de code que nous utilisons peut influencer l'opcode PHP résultant, dans le bon ou dans le mauvais sens. Commençons par coller le code ci-dessous dans 3v4l. Conservez la configuration "toutes les versions prises en charge" et cliquez sur "évaluer".
<?php namespace App; strlen('ciao');
Après avoir exécuté le code, un menu à onglets apparaîtra en bas. Accédez à l'onglet VLD pour visualiser l'OPcode correspondant.
line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 5 0 E > INIT_NS_FCALL_BY_NAME 'App%5CSpace%5Cstrlen' 1 SEND_VAL_EX 'ciao' 2 DO_FCALL 0 3 > RETURN 1
Notez que la première opération est INIT_NS_FCALL_BY_NAME. L'interpréteur construit le nom de la fonction en utilisant l'espace de noms du fichier actuel. Mais il n'existe pas dans l'espace de noms AppExample, alors comment ça marche ?
L'interpréteur vérifiera si la fonction existe dans l'espace de noms actuel. Si ce n’est pas le cas, il essaie d’appeler la fonction principale correspondante.
Ici, nous avons la possibilité de dire à l'interprète d'éviter cette double vérification et d'exécuter directement la fonction principale.
Essayez d'ajouter une barre oblique inverse () avant strlen et cliquez sur "eval":
<?php namespace App; \strlen('ciao');
Dans l'onglet VLD, vous pouvez maintenant voir l'opcode avec une seule instruction.
line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 5 0 E > > RETURN 1
C'est parce que vous avez communiqué l'emplacement exact de la fonction, elle n'a donc pas besoin d'envisager une solution de secours.
Si vous n'aimez pas utiliser la barre oblique inverse, vous pouvez importer la fonction comme n'importe quelle autre classe à partir de l'espace de noms racine :
// Force compilation of a script opcache_compile_file(__DIR__.'/yourscript.php'); // Get OPcache status $status = opcache_get_status(); // Inspect the script's entry in the cache print_r($status['scripts'][__DIR__.'/yourscript.php']);
Il existe également de nombreux automatismes internes au moteur PHP pour générer un opcode optimisé évaluant au préalable les expressions statiques. C'est l'une des raisons les plus importantes de la grande amélioration des performances de PHP depuis la version 7.x
Être conscient de ces dynamiques peut vraiment vous aider à réduire la consommation de ressources et à réduire les coûts. Une fois cette recherche effectuée, j'ai commencé à utiliser ces astuces tout au long du code.
Laissez-moi vous montrer un exemple utilisant des constantes PHP. Exécutez ce script en 3v4l :
php -d vld.active=1 -d vld.execute=0 yourscript.php
Jetez un oeil aux deux premières lignes de l'opcode PHP :
<?php namespace App; strlen('ciao');
FETCH_CONSTANT essaie d'obtenir la valeur de PHP_OS à partir de l'espace de noms actuel et il examinera l'espace de noms global car il n'existe pas ici. Ensuite, l'instruction IS_IDENTICAL exécute l'instruction IF.
Essayez maintenant d'ajouter la barre oblique inverse à la constante :
line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 5 0 E > INIT_NS_FCALL_BY_NAME 'App%5CSpace%5Cstrlen' 1 SEND_VAL_EX 'ciao' 2 DO_FCALL 0 3 > RETURN 1
Comme vous pouvez le voir dans l'opcode, le moteur n'a pas besoin d'essayer de récupérer la constante car maintenant il est clair où elle se trouve, et comme c'est une valeur statique, il l'a déjà en mémoire.
L'instruction IF a également disparu car l'autre côté de l'instruction IS_IDENTITCAL est une chaîne statique (« Linux »), de sorte que l'instruction IF peut être marquée comme « vrai » sans avoir à l'interpréter à chaque exécution.
C'est pourquoi vous disposez de beaucoup de pouvoir pour influencer les performances ultimes de votre code PHP.
J'espère que c'était un sujet intéressant, comme je l'ai mentionné au début de l'article, je tire beaucoup d'avantages de l'utilisation de cette tactique et en fait, elles sont également utilisées dans nos packages.
Vous pouvez voir ici un exemple de la façon dont j'ai utilisé ces astuces dans notre package PHP pour optimiser ses performances : https://github.com/inspector-apm/inspector-php/blob/master/src/Inspector.php# L302
Pour des articles plus techniques vous pouvez me suivre sur Linkedin ou X.
Inspector est un outil de surveillance de l'exécution de code spécialement conçu pour les développeurs de logiciels. Vous n'avez pas besoin d'installer quoi que ce soit au niveau du serveur, installez simplement le package Laravel ou Symfony et vous êtes prêt à partir.
Si vous recherchez une surveillance HTTP, des informations sur les requêtes de base de données et la possibilité de transférer des alertes et des notifications vers votre environnement de messagerie préféré, essayez Inspector gratuitement. Enregistrez votre compte.
Ou apprenez-en plus sur le site : https://inspector.dev
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!