Byte-Code-Cache
Die Ideenschmiede schlägt heute das erste mal seit langer Zeit wieder zu, aber ich hatte ja angekündigt, dass ich sie jetzt ein bisschen weniger stiefmütterlich behandeln will. Heute also das erste Thema, dass von 28 Leuten gewählt wurde: „Was sind eigentlich Byte-Code-Caches?“
Holen wir mal ein wenig aus. PHP kennt man als interpretierte Sprache, was nicht so ganz richtig ist. Wie bei Java wird plattformunabhängiger Byte-Code erstellt, welcher später von der Zend-Engine ausgeführt wird. Dies geschieht im Normalfall bei jedem Ausführen eines Skriptes. Um den Byte-Code zu erstellen muss PHP erstmal den Code lexen (Zerlegen in Token) und danach parsen. Dies kann je nach Anzahl der inkludieren PHP-Dateien einen großen Anteil der Laufzeit des Skriptes bedeuten. Und was das schlimmste ist: eigentlich ändert sich der Byte-Code so gut wie nie.
Beispiel
Auszuführender PHP-Code
$output = „Hello World!“; echo $output; return;
Resultierender Byte-Code
ASSIGN !0 ‚Hello+World%21‘ ECHO !0 RETURN 1 ZEND_HANDLE_EXCEPTION
Zum Glück ist das System rund um die Zend-Engine so konstruiert, dann man Caches einhängen kann, die den Byte-Code vorhalten und nur bei Änderungen lexen und parsen, was einen enormen Geschwindigkeitszuwachs bedeuten kann. In meinem Fall sind es sogar bis zu 300%, was wohl wirklich der Rede wert ist.
Wer auf Nummer sicher gehen will, der installiert sich APC als wohl gängigstes Cache-System. Es gibt aber jede Menge weiterer Vertreter, die fast alle das gleiche machen. Schönes Feature von APC ist noch, dass er als normaler In-Memory-Cache verwendet werden kann und erweitert somit die Grundfunktionalität von PHP um ein paar Befehle.
So das war jetzt erstmal ein grober Überblick. Ich werde wohl noch einen Artikel direkt zu APC schreiben, damit da auch alle Feinheiten (die ich kenne) unter kommen.
Läuft der Byte-Code-Cache lediglich auf Zend Server Maschinen oder ist die Zend Engine der generelle PHP-Parser? Denn 300% sind nun wirklich nicht verachten. 🙂
Wenn du einen Artikel zum Thema APC schreiben möchtest, wäre vielleicht mal ein Abschnitt über die Optimierung der Einstellung und deren Auswirkungen toll. Wieviel Ram sollte man für den APC zur Verfügung stellen? Gibt es ab einer gewissen Grenze noch einen Geschwindigkeitszuwachs oder reichen bspw 128MB vollkommen aus?
@Tobi: Zend Engine und Zend Server sind zwei komplett verschiedene Dinge. Die Zend Engine ist PHPs interne Laufzeitumgebung, während der Zend Server ein Bundle aus Apache, PHP, Datenbank und co – von der Firma Zend bereitgestellt – ist.
@Tobi: Ist der PHP-Interpreter. http://de.wikipedia.org/wiki/Zend_Engine
Byte Code Caches hängen sich in den Interpreter rein und damit sollten die überall laufen.
@Martin & Norbert: danke Euch für die Aufklärung. Wieder was gelernt heute. 🙂
@Norbert: viel verstellen braucht man da nicht. Dir Größe sollte so groß sein das alle Projektdaten drin abgelegt werden können. Ansonsten ist stat = 0 zu setzen, damit die Festplatte entlastet wird. Alle anderen Settings geben keine signifikanten Geschwindigkeitsvorteile.
@Nils: Mit welcher Anweisung kommst du vom „auszuführenden PHP-Code“ auf den „resultierenden Byte-Code“? token_get_all?
Zum Thema apc-usage: http://devzone.zend.com/article/12618 🙂
@Jens: Soviel ich weiß, bekommst du den Byte-Code gar nicht in PHP produziert. Der erste Schritt dorthin, also das Lexen, funktioniert über die token_get_all-Funktion. Mein Beispiel hatte ich aus einer Doku zum Thema APC.
Wir hatten heute passender Weise in der Firma nen Techtalk über PHP-Interna, da sind wir auch an Opcode-Caches (so heißts richtig) geraten. Bei uns allerdings dann eaccelerator statt APC.
An die Opcodes kommt man mit dem Vulcan Logic Dumper http://derickrethans.nl/projects.html#vld
http://pecl.php.net/package/vld
Einfach die Extension installieren, nicht aktivieren, und dann via CLI nen PHP-Script aufrufen und dort mit der Option „-dvld.active=1“ den Dumper zuschalten.
Was noch weit aus interessanter ist: Die Opcode-Caches, zumind eaccelerator, optimieren die Opcodes auch. PHP bastelt die nach dem Lexen nämlich sehr stumpf, dumm und semioptimal zusammen. z.B. werden dann Rechenoperationen mit Konstanten direkt durch die Ergebnisse ersetzt oder Ketten von Jumps durch einzelne Jumps direkt auf das Endziel ersetzt.