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 une évidence 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 vus 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, 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.
Das Zwischenspeichern des vorkompilierten Skript-Bytecodes erfordert die Ungültigmachung des Caches nach jeder Bereitstellung. Denn wenn geänderte Dateien die Bytecode-Version im Cache haben, führt PHP weiterhin die alte Version des Codes aus. Bis Sie den Opcode-Cache leeren, damit der neue Code erneut kompiliert wird und ein neues Cache-Element generiert wird.
Um zu verstehen, wie sich eine unterschiedliche Syntax auf den Opcode des Skripts auswirken kann, benötigen wir eine Möglichkeit, den von der PHP-Engine generierten kompilierten Code abzurufen.
Es gibt zwei Möglichkeiten, den Opcode zu erhalten.
Wenn Sie die OPCache-Erweiterung auf Ihrem Computer aktiviert haben, können Sie ihre nativen Funktionen verwenden, um den Opcode einer bestimmten PHP-Datei abzurufen:
// 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 ist eine beliebte PHP-Erweiterung, die kompilierten PHP-Code zerlegt und den Opcode ausgibt. Es ist ein leistungsstarkes Tool, um zu verstehen, wie PHP Ihren Code interpretiert und ausführt. Nach der Installation können Sie ein PHP-Skript mit aktiviertem VLD ausführen, indem Sie den PHP-Befehl mit den Optionen -d verwenden:
php -d vld.active=1 -d vld.execute=0 yourscript.php
Die Ausgabe enthält detaillierte Informationen zum kompilierten Opcode, einschließlich jeder Operation, der zugehörigen Codezeile und mehr.
3v4l ist ein sehr nützliches Online-Tool, mit dem Sie den Opcode anzeigen können, der von einem PHP-Code generiert wird, den Sie in den Editor eingeben. Es handelt sich im Grunde um einen PHP-Server mit installiertem VLD, sodass er die VLD-Ausgabe abrufen und Ihnen den Opcode im Browser anzeigen kann.
Da es kostenlos erhältlich ist, werden wir dieses Online-Tool für die nächsten Analysen verwenden.
3v4l ist perfekt, um zu verstehen, wie die von uns verwendete Codesyntax den resultierenden PHP-Opcode positiv oder negativ beeinflussen kann. Beginnen wir mit dem Einfügen des folgenden Codes in 3v4l. Behalten Sie die Konfiguration „Alle unterstützten Versionen“ bei und klicken Sie auf „Evaluieren“.
<?php namespace App; strlen('ciao');
Nach der Ausführung des Codes erscheint unten ein Tab-Menü. Navigieren Sie zur Registerkarte VLD, um den entsprechenden OPcode anzuzeigen.
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
Beachten Sie, dass die erste Operation INIT_NS_FCALL_BY_NAME ist. Der Interpreter erstellt den Namen der Funktion unter Verwendung des Namensraums der aktuellen Datei. Aber es existiert nicht im AppExample-Namespace. Wie funktioniert es also?
Der Interpreter prüft, ob die Funktion im aktuellen Namespace vorhanden ist. Ist dies nicht der Fall, wird versucht, die entsprechende Kernfunktion aufzurufen.
Hier haben wir die Möglichkeit, den Interpreter anzuweisen, diese doppelte Prüfung zu vermeiden und die Kernfunktion direkt auszuführen.
Versuchen Sie, vor strlen einen Backslash () einzufügen und klicken Sie auf „eval“:
<?php namespace App; \strlen('ciao');
Im VLD-Tab können Sie jetzt den Opcode mit nur einer Anweisung sehen.
line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 5 0 E > > RETURN 1
Das liegt daran, dass Sie den genauen Standort der Funktion mitgeteilt haben, sodass kein Fallback berücksichtigt werden muss.
If don't like to use the the backslash, you can import the function like any other class from the root namespace:
<?php namespace App; use function strlen; strlen('ciao');
There are also a lot of internal automatisms of the PHP engine to generate an optimized opcode evaluating static expressions in advance. This was one of the most important reasons of the great performance improvement of PHP since the version 7.x
Being aware of these dynamics can really help you reduce resource consumption and cut costs. Once I made this research, I started using these tricks throughout the code.
Let me show you an example using PHP constants. Run this script into 3v4l:
<?php namespace App; if (PHP_OS === 'Linux') { echo "Linux"; }
Take a look at the first two lines of the PHP opcode:
line #* E I O op fetch ext return operands ------------------------------------------------------------------------------------- 5 0 E > FETCH_CONSTANT ~0 'App%5CPHP_OS' 1 IS_IDENTICAL ~0, 'Linux' 2 > JMPZ ~1, ->4 6 3 > ECHO 'Linux' 7 4 > > RETURN 1
FETCH_CONSTANT try to get the value of PHP_OS from the current namespace and it will look into the global namespace as it doesn’t exist here. Then the IS_IDENTICAL instruction executes the IF statement.
Now try adding the backslash to constant:
<?php namespace App; if (\PHP_OS === 'Linux') { echo "Linux"; }
As you can see in the opcode the engine doesn't need to try to fetch the constant because now it's clear where it is, and since it's a static value it already has it in memory.
Also the IF statement disappeared because the other side of the IS_IDENTITCAL statement is a static string ('Linux') so the IF can be marked as "true" without the overhead of interpreting it on every execution.
This is why you have a lot of power to influence the ultimate performance of your PHP code.
I hope it was an interesting topic, as I mentioned at the beginning of the article I'm getting a lot of benefits from using this tactic and in fact they are also used in our packages.
You can see here an example of how I used this tips in our PHP package to optimize its performance: https://github.com/inspector-apm/inspector-php/blob/master/src/Inspector.php#L302
For more technical articles you can follow me on Linkedin or X.
Inspector is a Code Execution Monitoring tool specifically designed for software developers. You don't need to install anything at the server level, just install the Laravel or Symfony package and you are ready to go.
If you are looking for HTTP monitoring, database query insights, and the ability to forward alerts and notifications into your preferred messaging environment, try Inspector for free. Register your account.
Or learn more on the website: 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!