Der von der PHP-Engine generierte PHP-Opcode wird stark von der Art und Weise beeinflusst, wie Sie Ihren Code schreiben. Nicht nur im Hinblick auf die Anzahl der Anweisungen zur Erfüllung einer Aufgabe. Offensichtlich ist es sehr wichtig, und ich denke, es ist für Sie offensichtlich.
Was weniger offensichtlich sein könnte, ist, dass selbst die Syntax des Codes den generierten Opcode vollständig ändern kann, was einen hohen Overhead für die CPU der Maschine verursacht, um genau denselben Code auszuführen.
In den letzten Jahren ist mein SaaS-Produkt stark gewachsen und es hat mir die Möglichkeit gegeben, immer tiefer in die Optimierungstechniken einzusteigen, um meine Arbeitslast so effizient wie möglich auszuführen.
Die Ergebnisse, die ich gesehen habe, sind beeindruckend und haben mir sehr dabei geholfen, freien Cashflow freizusetzen, um meine SaaS-Reise weiterzuentwickeln.
Zu diesem Zeitpunkt verarbeitet der PHP-Prozess in meinem SaaS-Produkt täglich mehr als 1,2 Milliarden (mit B) Datenpakete auf einer Maschine mit 2vCPU und 8GB Arbeitsspeicher. Ich verwende eine AWS-Autoscaling-Gruppe, um bei unvorhersehbaren Spitzen mehr Flexibilität zu haben, aber sie fügt selten eine zweite Maschine hinzu (ein- oder zweimal pro Woche).
Für weitere technische Artikel können Sie mir auf Linkedin oder X folgen.
Kürzlich habe ich auch über die Migration der Inspector-Server auf ARM-Instanzen geschrieben: https://inspector.dev/inspector-adoption-of-graviton-arm-instances-and-what-results-weve-seen/
Lassen Sie uns auf das Thema des Artikels eingehen. Ich denke, Sie werden es sehr interessant finden.
PHP-Opcode steht für Operationscode und bezieht sich auf die Low-Level-Anweisungen, die von der PHP-Engine ausgeführt werden, nachdem der von Ihnen geschriebene PHP-Quellcode kompiliert wurde.
In PHP erfolgt die Codekompilierung zur Laufzeit. Wenn Ihr Code zum ersten Mal von der PHP-Engine übernommen wird, wird er in diesen maschinenfreundlichen Code kompiliert und zwischengespeichert, damit die Engine denselben Code nicht erneut kompiliert dann ausgeführt.
Dies ist eine einfache Darstellung des Prozesses:
Durch das Zwischenspeichern des PHP-Opcodes können Sie drei Schritte bei der Ausführung des Codes einsparen: Parsen des rohen PHP-Codes, Tokenisierung und Kompilierung.
Sobald der Opcode zum ersten Mal generiert wird, wird er im Speicher gespeichert, sodass er in nachfolgenden Anforderungen wiederverwendet werden kann. Dies reduziert die Notwendigkeit, dass die PHP-Engine bei jeder Ausführung denselben PHP-Code neu kompilieren muss, was viel CPU- und Speicherverbrauch spart.
Der am häufigsten verwendete Opcode-Cache in PHP ist OPCache und ist seit PHP 5.5 bis zu neueren Versionen standardmäßig enthalten. Es ist hocheffizient und wird weithin unterstützt.
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. Im Grunde handelt es sich 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.
Wenn Sie den Backslash nicht verwenden möchten, können Sie die Funktion wie jede andere Klasse aus dem Root-Namespace importieren:
// 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']);
Es gibt auch viele interne Automatismen der PHP-Engine, um einen optimierten Opcode zu generieren, der statische Ausdrücke im Voraus auswertet. Dies war einer der wichtigsten Gründe für die große Leistungsverbesserung von PHP seit der Version 7.x
Wenn Sie sich dieser Dynamik bewusst sind, können Sie den Ressourcenverbrauch und die Kosten erheblich senken. Nachdem ich diese Recherche durchgeführt hatte, begann ich, diese Tricks im gesamten Code anzuwenden.
Lassen Sie mich Ihnen ein Beispiel mit PHP-Konstanten zeigen. Führen Sie dieses Skript in 3v4l aus:
php -d vld.active=1 -d vld.execute=0 yourscript.php
Sehen Sie sich die ersten beiden Zeilen des PHP-Opcodes an:
<?php namespace App; strlen('ciao');
FETCH_CONSTANT versucht, den Wert von PHP_OS aus dem aktuellen Namespace abzurufen und sucht im globalen Namespace, da dieser hier nicht existiert. Dann führt die Anweisung IS_IDENTICAL die IF-Anweisung aus.
Versuchen Sie nun, den Backslash zur Konstante hinzuzufügen:
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
Wie Sie im Opcode sehen können, muss die Engine nicht versuchen, die Konstante abzurufen, da jetzt klar ist, wo sie sich befindet, und da es sich um einen statischen Wert handelt, hat sie ihn bereits im Speicher.
Außerdem ist die IF-Anweisung verschwunden, da die andere Seite der IS_IDENTITCAL-Anweisung eine statische Zeichenfolge ('Linux') ist, sodass die IF als „wahr“ markiert werden kann, ohne dass der Aufwand für die Interpretation bei jeder Ausführung anfällt.
Aus diesem Grund haben Sie viel Einfluss auf die endgültige Leistung Ihres PHP-Codes.
Ich hoffe, es war ein interessantes Thema, denn wie ich am Anfang des Artikels erwähnt habe, erhalte ich viele Vorteile aus der Verwendung dieser Taktik und tatsächlich werden sie auch in unseren Paketen verwendet.
Hier können Sie ein Beispiel sehen, wie ich diese Tipps in unserem PHP-Paket verwendet habe, um dessen Leistung zu optimieren: https://github.com/inspector-apm/inspector-php/blob/master/src/Inspector.php# L302
Für weitere technische Artikel können Sie mir auf Linkedin oder X folgen.
Inspector ist ein Tool zur Codeausführungsüberwachung, das speziell für Softwareentwickler entwickelt wurde. Sie müssen nichts auf Serverebene installieren. Installieren Sie einfach das Paket Laravel oder Symfony und schon kann es losgehen.
Wenn Sie nach HTTP-Überwachung, Einblicken in Datenbankabfragen und der Möglichkeit suchen, Warnungen und Benachrichtigungen an Ihre bevorzugte Messaging-Umgebung weiterzuleiten, testen Sie Inspector kostenlos. Registrieren Sie Ihr Konto.
Oder erfahren Sie mehr auf der Website: https://inspector.dev
Das obige ist der detaillierte Inhalt vonPHP-Opcode – Verbessern Sie die Anwendungsleistung, ohne Ihren Code zu ändern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!