Function JIT, Tracing JIT und die Grenze zwischen Maschinencode und Syscall
Seit PHP 8.0 übersetzt der JIT-Compiler heiße Opcode-Pfade zur Laufzeit in nativen Maschinencode, doch der Effekt hängt vollständig vom Workload ab: Bei numerischen Berechnungen, Bildverarbeitung und dem Parsen großer Datenmengen sind spürbare Laufzeitgewinne messbar, während klassische, datenbanklastige Webanwendungen kaum profitieren, weil dort die Wartezeit auf Syscalls dominiert. Dieser Artikel erklärt die Architektur von Function JIT und Tracing JIT, die relevanten opcache.jit-Konfigurationswerte und eine belastbare Benchmark-Methodik, um den tatsächlichen Effekt im eigenen Projekt zu messen statt zu vermuten.
Inhaltsverzeichnis
- 1. Was der JIT-Compiler in PHP 8 wirklich macht
- 2. Tracing JIT vs. Function JIT: Architekturunterschiede
- 3. opcache.jit und opcache.jit_buffer_size konfigurieren
- 4. Hot-Thresholds: jit_hot_func, jit_hot_loop, jit_hot_side_exit
- 5. Wann der JIT-Compiler tatsächlich hilft
- 6. Wann der JIT-Compiler nichts bringt
- 7. Benchmark-Methodik: den JIT-Impact korrekt messen
- 8. Bekannte Probleme: Debugging, Xdebug, Extensions
- 9. Produktionsempfehlung: aktivieren, deaktivieren, differenzieren
- 10. Zusammenfassung
- 11. FAQ
1. Was der JIT-Compiler in PHP 8 wirklich macht
Die Zend Engine übersetzt PHP-Quellcode zunächst in Opcodes, die kompakte Bytecode-Repräsentation, die von der Zend Virtual Machine interpretiert wird. OPcache cacht diese kompilierten Opcodes im Shared Memory, damit Parsing und Kompilierung nicht bei jedem Request wiederholt werden müssen. Das ist bereits ein erheblicher Performance-Gewinn gegenüber unkompiliertem PHP, hat aber mit dem eigentlichen Compiler-Feature selbst noch nichts zu tun: Die Opcodes werden weiterhin Zeile für Zeile von der Zend VM interpretiert, nur eben ohne wiederholtes Parsen.
Der JIT-Compiler geht einen entscheidenden Schritt weiter. Er nimmt die Zend-VM-Opcodes für als "heiß" erkannten Code und übersetzt sie zur Laufzeit direkt in nativen Maschinencode für die jeweilige CPU-Architektur. Dieser Maschinencode wird anschließend direkt von der CPU ausgeführt, ohne den Umweg über die Dispatch-Schleife des Interpreters. Der dafür reservierte Speicherbereich ist ein eigener Shared-Memory-Block, getrennt vom klassischen OPcache-Bytecode-Cache, und wird über opcache.jit_buffer_size dimensioniert.
Ein verbreitetes Missverständnis ist, er ersetze OPcache. Tatsächlich ist er eine Erweiterung, die auf einem aktivierten OPcache aufsetzt: Ohne opcache.enable=1 funktioniert auch er nicht, weil er auf denselben internen Strukturen der bereits kompilierten Opcodes arbeitet. Bytecode-Cache und Maschinencode-Übersetzung sind zwei unterschiedliche, aufeinander aufbauende Optimierungsstufen im selben Modul.
2. Tracing JIT vs. Function JIT: Architekturunterschiede
PHP kennt zwei grundsätzlich unterschiedliche Kompilierungsstrategien für den JIT-Compiler. Der Function JIT kompiliert eine komplette Funktion zu Maschinencode, sobald ihr Aufrufzähler den konfigurierten Schwellenwert erreicht. Dabei wird der gesamte Funktionskörper übersetzt, einschließlich selten durchlaufener Zweige, ohne die tatsächlich zur Laufzeit beobachteten Typen gezielt auszunutzen. Die Kompilierung erfolgt vollständig anhand statisch verfügbarer Typinformationen.
Der Tracing JIT verfolgt dagegen tatsächlich durchlaufene, heiße Pfade: konkrete Schleifen, die häufig iterieren, oder Seitenpfade, die durch Abweichungen von einem bestehenden Trace entstehen. Dabei zeichnet er die während der Ausführung real beobachteten Typen auf und erzeugt hochspezialisierten Maschinencode genau für diesen einen Pfad. Weicht die Ausführung vom aufgezeichneten Trace ab, springt die Ausführung zurück in den Interpreter, ein sogenannter Side Exit. Dieser Ansatz erlaubt aggressivere Optimierungen als Function JIT, weil Typprüfungen entfallen können, die im generischen Fall nötig wären, bringt aber zusätzliche Komplexität beim Debugging mit sich, weil kompilierter Code nur für exakt beobachtete Pfade existiert.
Seit PHP 8.0 ist Tracing JIT der Standardmodus, weil er in realistischen Benchmarks tendenziell bessere Ergebnisse liefert als Function JIT. Function JIT bleibt dennoch relevant, etwa wenn ein vorhersagbareres Kompilierungsverhalten mit weniger Varianz gewünscht ist oder wenn eine Codebasis viele kleine, gleichmäßig aufgerufene Funktionen statt langlaufender Schleifen enthält.
3. opcache.jit und opcache.jit_buffer_size konfigurieren
Der Wert von opcache.jit folgt einem vierstelligen Schema, das CPU-spezifische Optimierungen, Registerallokation, Trigger-Verhalten und Optimierungsstufe kodiert. In der Praxis reicht es, sich die gängigen Presets zu merken: 1205 aktiviert Function JIT, 1254 aktiviert Tracing JIT und ist seit PHP 8.0 der Default. Wer den JIT-Compiler vollständig abschalten will, setzt opcache.jit=disable oder alternativ opcache.jit_buffer_size=0, denn ein Buffer der Größe null deaktiviert ihn unabhängig vom gewählten Modus.
opcache.jit_buffer_size bestimmt die Größe des Shared-Memory-Bereichs, in dem der kompilierte Maschinencode abgelegt wird. Ist dieser Bereich zu klein dimensioniert, kann er irgendwann keinen weiteren Code mehr kompilieren und fällt für zusätzlichen heißen Code stillschweigend auf den Interpreter zurück, ohne Fehler oder Warnung. Über opcache_get_status()['jit']['buffer_free'] lässt sich zur Laufzeit prüfen, wie viel Platz noch frei ist. Für die meisten Anwendungen sind 64 bis 128 Megabyte ein sinnvoller Startwert, bei sehr großen Codebasen mit vielen heißen Funktionen kann mehr nötig sein.
; php.ini - JIT aktivieren (Tracing JIT, PHP-Default seit 8.0)
opcache.enable=1
opcache.enable_cli=1
; JIT-Buffer: separater Shared-Memory-Bereich fuer nativen Maschinencode.
; 0 = JIT vollstaendig deaktiviert, unabhaengig vom opcache.jit-Wert
opcache.jit_buffer_size=100M
; Vierstelliges Schema (CPU-Register, Allokation, Trigger, Optimierungsstufe)
; 1254 = Tracing JIT, Optimierungsstufe 4 (PHP-Default seit 8.0)
; 1205 = Function JIT, kompiliert ganze Funktionen ohne Trace-Spezialisierung
opcache.jit=1254
; Vollstaendig deaktivieren, z. B. fuer reine Debug-Umgebungen mit Xdebug
; opcache.jit=disable
Der Buffer sollte regelmäßig überwacht werden, insbesondere nach Deployments mit neuem, häufig durchlaufenem Code. Ein voller JIT-Buffer ist keine Fehlermeldung im klassischen Sinn, sondern ein stiller Rückfall auf reine Interpretation, der die erwarteten Performance-Gewinne unbemerkt zunichtemacht.
4. Hot-Thresholds: jit_hot_func, jit_hot_loop, jit_hot_side_exit
Der JIT-Compiler kompiliert nicht jeden Code sofort, weil Kompilierung selbst Rechenzeit kostet. Drei Schwellenwerte steuern, ab wann Code als heiß gilt. opcache.jit_hot_func definiert die Anzahl der Aufrufe, bevor eine Funktion durch Function JIT kompiliert wird, standardmäßig 127. opcache.jit_hot_loop definiert die Anzahl der Schleifeniterationen, bevor Tracing JIT einen Trace für diese Schleife anlegt, standardmäßig 61. opcache.jit_hot_side_exit definiert, wie oft ein Trace an derselben Stelle verlassen werden muss, bevor für den abweichenden Pfad ein eigener, spezialisierter Trace kompiliert wird, standardmäßig 8.
Diese Schwellenwerte verhindern, dass er Zeit in die Übersetzung von Code investiert, der ohnehin nur ein- oder zweimal ausgeführt wird. Der Kompilierungsaufwand amortisiert sich erst, wenn der Code oft genug läuft, um den Overhead der Übersetzung durch die spätere Ausführungsgeschwindigkeit auszugleichen. Niedrigere Schwellenwerte lassen ihn früher eingreifen, erhöhen aber das Risiko, Code zu kompilieren, der letztlich doch nicht heiß genug bleibt. Höhere Schwellenwerte verzögern den Effekt, reduzieren aber unnötige Kompilierungsarbeit für tatsächlich kalten Code.
; php.ini - Hot-Thresholds fuer den JIT (ab wann gilt Code als heiss?)
; Ab wann gilt Code als "heiss" und wird zu Maschinencode kompiliert?
; Aufrufzaehler pro Funktion, bevor Function JIT sie kompiliert (Default: 127)
opcache.jit_hot_func=127
; Iterationszaehler pro Schleife, bevor Tracing JIT einen Trace startet (Default: 61)
opcache.jit_hot_loop=61
; Anzahl Side-Exits an derselben Stelle, bevor ein eigener Trace fuer den
; abweichenden Pfad kompiliert wird (Default: 8)
opcache.jit_hot_side_exit=8
; Niedrigere Werte: greift frueher, aber hoeheres Risiko von
; Kompilierungs-Overhead fuer Code, der nicht dauerhaft heiss bleibt.
5. Wann der JIT-Compiler tatsächlich hilft
CPU-gebundene Workloads profitieren am deutlichsten vom JIT-Compiler: numerische Berechnungen wie Matrixoperationen und physikalische Simulationen, Bildverarbeitung mit pixelweisen Operationen, Verschlüsselungs- und Hash-Routinen, die nicht bereits in einer C-Extension implementiert sind, das Parsen großer Datenmengen Zeichen für Zeichen sowie Machine-Learning-Vorverarbeitung mit Feature-Engineering-Schleifen in reinem PHP.
Der Grund liegt in der Natur dieser Workloads: Sie verbringen den Großteil ihrer Laufzeit in engen Schleifen, die wiederholt arithmetische und vergleichende Opcodes ausführen. Der Overhead der Zend-VM-Dispatch-Schleife, inklusive wiederholter Typprüfungen pro Opcode, dominiert in diesem Szenario die Ausführungszeit. Er eliminiert diesen Dispatch-Overhead, indem er direkt native Maschineninstruktionen erzeugt. Beim Tracing JIT entfällt durch Typspezialisierung zusätzlich ein erheblicher Teil der zur Laufzeit sonst nötigen Typprüfungen. In der Praxis zeigen Benchmarks für enge numerische Schleifen häufig Faktoren zwischen drei- und achtfacher Beschleunigung.
Klassische Beispiele aus der Praxis sind reine PHP-Implementierungen von Mandelbrot-Berechnungen, Sortieralgorithmen ohne native Beschleunigung oder rekursive numerische Funktionen. Überall dort, wo der Code selbst die Arbeit leistet, statt sie an eine C-Extension oder externe Ressource zu delegieren, entfaltet er sein volles Potenzial.
6. Wann der JIT-Compiler nichts bringt
I/O-gebundene Webanwendungen profitieren dagegen kaum vom JIT-Compiler. Datenbankabfragen, Netzwerk-Calls und Dateisystemzugriffe sind Syscalls, die vollständig außerhalb der Zend Engine ablaufen. Er kann nur Code beschleunigen, der tatsächlich von der Zend VM ausgeführt wird, nicht die Zeit, die ein Prozess wartend im Kernel verbringt, während eine MySQL-Query läuft oder eine HTTP-Antwort eintrifft.
Ein typischer Web-Request macht das Verhältnis deutlich: Wenige Millisekunden tatsächlicher CPU-gebundener PHP-Ausführung stehen oft mehreren Dutzend bis mehreren Hundert Millisekunden Wartezeit auf Datenbankantworten, externe API-Aufrufe oder Session-Storage gegenüber. Er wirkt sich ausschließlich auf den CPU-gebundenen Anteil aus, der bei vielen Webanwendungen deutlich unter fünf Prozent der gesamten Request-Zeit ausmacht. Selbst eine hypothetische fünffache Beschleunigung dieses kleinen Anteils bringt kaum spürbare Verbesserung der End-to-End-Antwortzeit.
Reale Benchmarks bestätigen das: Für typische, datenbanklastige Content-Management- und Shop-Anwendungen zeigen unabhängige Messungen häufig nur einstellige Prozentverbesserungen, während dieselben Messungen für reine Rechen-Benchmarks ein Vielfaches an Geschwindigkeit ausweisen. Wer ihn allein wegen generischer Marketing-Zahlen aktiviert, ohne den eigenen Workload zu kennen, wird in der Praxis regelmäßig enttäuscht.
7. Benchmark-Methodik: den JIT-Impact korrekt messen
Für Microbenchmarks eignet sich hrtime(true) deutlich besser als microtime(), weil es einen monotonen Zeitgeber in Nanosekunden ohne Anfälligkeit für Systemzeit-Anpassungen liefert. Entscheidend ist außerdem ein separates Warm-up: Da die Kompilierung durch den JIT-Compiler selbst Zeit benötigt und erst nach Erreichen der Hot-Thresholds einsetzt, muss der zu messende Code vor der eigentlichen Messung ausreichend oft durchlaufen werden. Wird direkt beim ersten Aufruf gemessen, fließt Interpretationszeit und Kompilierungsaufwand in das Ergebnis ein und die tatsächliche Spitzenleistung wird systematisch unterschätzt.
Microbenchmarks, isoliert über die CLI mit gezielten -d-Flags ausgeführt, unterscheiden sich erheblich von realen Workloads in einem Webserver-Kontext. Lang laufende PHP-FPM-Worker teilen sich den JIT-Buffer über mehrere Requests hinweg, während ein opcache_reset() oder ein Prozessneustart bereits kompilierten Code wieder verwirft. Häufige Messfehler entstehen durch zu kurze Laufzeiten, bei denen die Auflösung des Zeitgebers, Garbage-Collector-Pausen oder Scheduling-Jitter des Betriebssystems das Ergebnis stärker beeinflussen als der eigentlich gemessene Effekt.
<?php
declare(strict_types=1);
/**
* Microbenchmark: CPU-bound function with and without the JIT compiler.
* Run twice from the CLI to compare:
* php -d opcache.jit=0 bench.php (interpreter only)
* php -d opcache.jit=1254 -d opcache.jit_buffer_size=64M bench.php (JIT compiler on)
*/
function isPrime(int $n): bool
{
if ($n < 2) {
return false;
}
for ($i = 2; $i * $i <= $n; $i++) {
if ($n % $i === 0) {
return false;
}
}
return true;
}
function countPrimes(int $limit): int
{
$count = 0;
for ($n = 2; $n <= $limit; $n++) {
if (isPrime($n)) {
$count++;
}
}
return $count;
}
// Warm-up: let the JIT compiler reach the hot-function/hot-loop thresholds
// and finish compiling before the actual measurement starts.
countPrimes(200_000);
$iterations = 5;
$samples = [];
for ($i = 0; $i < $iterations; $i++) {
$start = hrtime(true);
$result = countPrimes(2_000_000);
$elapsedMs = (hrtime(true) - $start) / 1_000_000;
$samples[] = $elapsedMs;
}
$avg = array_sum($samples) / count($samples);
printf("Primes found: %d\n", $result);
printf("Average runtime over %d runs: %.2f ms\n", $iterations, $avg);
printf("Samples (ms): %s\n", implode(', ', array_map(fn($v) => round($v, 2), $samples)));
Wichtig für belastbare Ergebnisse: Mehrere Wiederholungen messen, Mittelwert und Streuung betrachten statt eines einzelnen Laufs, und die Messung sowohl mit deaktivierter als auch mit aktivierter JIT-Kompilierung auf identischer Hardware unter identischer Systemlast durchführen. Nur der direkte Vergleich unter sonst gleichen Bedingungen liefert eine belastbare Aussage über den tatsächlichen Effekt.
8. Bekannte Probleme: Debugging, Xdebug, Extensions
Debugging mit aktivierter JIT-Kompilierung ist grundsätzlich möglich, aber stellenweise unbequemer. Da kompilierter Maschinencode nicht in jedem Fall eins zu eins auf Quellcodezeilen zurückführbar ist, können bestimmte Low-Level-Debugging-Szenarien mit Werkzeugen wie gdb erschwert sein. Für den alltäglichen Anwendungsfall mit var_dump(), Logging und Exceptions ändert sich hingegen nichts, weil diese Mechanismen unabhängig davon funktionieren, ob der zugrunde liegende Opcode gerade interpretiert oder als Maschinencode ausgeführt wird.
Deutlich relevanter ist die Interaktion mit Xdebug. Xdebug hakt sich tief in die Ausführung der Zend VM ein, um Step-Debugging, Coverage und Profiling auf Opcode-Ebene zu ermöglichen. Diese Instrumentierung ist mit nativ ausgeführtem Maschinencode nicht kompatibel, weshalb PHP den JIT-Compiler automatisch deaktiviert, sobald Xdebug in einem aktiven Modus geladen ist, unabhängig davon, welcher Wert für opcache.jit konfiguriert ist. Das ist kein Bug, sondern bewusstes Verhalten, das Debugging-Korrektheit über Performance stellt.
# Check whether the JIT compiler is actually active at runtime
php -r 'var_dump(opcache_get_status()["jit"]["enabled"]);'
# bool(true) -- plain opcache.jit=1254 configuration, Xdebug not loaded
php -d zend_extension=xdebug -r 'var_dump(opcache_get_status()["jit"]["enabled"]);'
# bool(false) -- Xdebug forces the JIT compiler off, regardless of opcache.jit
# Confirm which extensions are actually loaded for this SAPI/process
php -v
php -m | grep -i xdebug
Auch bei einigen C-Extensions, die sich tief in interne Zend-VM-Strukturen oder Opcode-Handler einklinken, sind vereinzelt Kompatibilitätsprobleme dokumentiert worden, insbesondere bei älteren, wenig gepflegten Extensions. Vor einer produktiven Aktivierung empfiehlt sich daher ein gezielter Kompatibilitätstest der eingesetzten Extension-Landschaft, statt sich ausschließlich auf generelle Aussagen zur PHP-Kernkompatibilität zu verlassen.
9. Produktionsempfehlung: aktivieren, deaktivieren, differenzieren
Es gibt keine pauschal richtige Antwort, ob der JIT-Compiler in Produktion aktiviert werden sollte. Die Entscheidung hängt vollständig vom tatsächlichen, durch Profiling ermittelten Workload-Profil ab, nicht von Vermutungen. Für klassische PHP-FPM-Anwendungen mit Request-pro-Prozess-Modell, die überwiegend durch Datenbankzugriffe und Netzwerk-I/O dominiert werden, bringt seine Aktivierung erfahrungsgemäß nur wenige Prozent Verbesserung, während zusätzliche Komplexität beim Debugging und zusätzlicher Speicherbedarf für den JIT-Buffer entstehen, ein Aufwand, der dem geringen Nutzen oft nicht gerecht wird.
Für dedizierte CPU-gebundene Batch- und Worker-Prozesse, etwa Report-Generierung, Bildverarbeitungs-Pipelines, Datenexport- und Importjobs oder rechenintensive Queue-Consumer, ergibt eine gezielte Aktivierung dagegen deutlich mehr Sinn. Solche Prozesse lassen sich über eigene PHP-FPM-Pools oder gezielte CLI-Aufrufe mit eigenem opcache.jit-Wert und größerem jit_buffer_size ausstatten, unabhängig von der Konfiguration des restlichen Web-Traffics.
# Web pool (PHP-FPM): I/O-bound requests, JIT compiler brings little value
# pool.d/www.conf
; php_admin_value[opcache.jit] = off
; php_admin_value[opcache.jit_buffer_size] = 0
# Worker pool (PHP-FPM): CPU-bound batch, export and report jobs
# pool.d/worker.conf
; php_admin_value[opcache.jit] = 1254
; php_admin_value[opcache.jit_buffer_size] = 128M
# Standalone CLI batch job with the JIT compiler enabled explicitly
php -d opcache.jit=1254 -d opcache.jit_buffer_size=128M bin/export-report.php
Wichtig ist, realistische Erwartungen zu setzen: Er ist kein pauschaler Performance-Schalter, sondern ein gezieltes Werkzeug für einen bestimmten Workload-Typ. Wer die eigene Anwendung vor der Entscheidung profiliert und den CPU-gebundenen Anteil tatsächlich beziffert, trifft eine begründete Entscheidung statt einer geratenen.
| Workload-Typ | JIT-Nutzen | Begründung |
|---|---|---|
| Numerische Berechnung | deutlich | Enge Schleifen, viele Opcode-Dispatches, kaum I/O-Wartezeit |
| Bildverarbeitung | deutlich | Pixelweise Operationen, wiederholte Arithmetik pro Pixel |
| DB-Query-lastiger Request | gering | Wartezeit auf Datenbankantworten dominiert die Gesamtlaufzeit |
| API-Proxy / Netzwerk-I/O | keiner | Syscalls und Netzwerklatenz werden vom JIT-Compiler nicht beschleunigt |
| Template-Rendering | gering | Meist Cache- und Storage-I/O, wenig reine CPU-Rechenlast |
Die Tabelle macht deutlich, dass die Entscheidung für oder gegen den JIT-Compiler keine Frage genereller PHP-Version oder genereller Best Practice ist, sondern eine Frage des konkreten Anteils an CPU-gebundener Rechenzeit im jeweiligen Workload. Wer diesen Anteil kennt, kann die Konfiguration gezielt darauf ausrichten, statt sie pauschal für die gesamte Infrastruktur zu übernehmen.
10. Zusammenfassung
Der JIT-Compiler in PHP 8 übersetzt heiße Opcode-Pfade zur Laufzeit in nativen Maschinencode und ist damit klar von der klassischen Bytecode-Cache-Funktion von OPcache zu unterscheiden. Function JIT kompiliert ganze Funktionen anhand von Aufrufzählern, Tracing JIT verfolgt konkrete, typspezialisierte Ausführungspfade und ist seit PHP 8.0 der Standardmodus. Die Konfiguration über opcache.jit, opcache.jit_buffer_size und die Hot-Thresholds jit_hot_func, jit_hot_loop sowie jit_hot_side_exit steuert, wann und wie aggressiv kompiliert wird.
Der entscheidende Faktor für den tatsächlichen Nutzen ist der Workload: CPU-gebundene Berechnungen profitieren deutlich, I/O-gebundene Webanwendungen kaum, weil der JIT-Compiler keine Syscalls beschleunigen kann. Xdebug deaktiviert ihn automatisch, und eine saubere Benchmark-Methodik mit hrtime(), Warm-up und mehreren Messläufen ist Voraussetzung für belastbare Aussagen. Die Produktionsempfehlung lautet daher: profilieren, den CPU-gebundenen Anteil beziffern, und ihn dort gezielt einsetzen, wo er wirklich etwas bringt, statt pauschal überall zu aktivieren oder zu deaktivieren.
Der JIT-Compiler in PHP 8, das Wichtigste auf einen Blick
Was er macht
Übersetzt heiße Zend-VM-Opcodes zur Laufzeit in nativen Maschinencode, getrennt vom klassischen OPcache-Bytecode-Cache.
Function JIT vs. Tracing JIT
Function JIT kompiliert ganze Funktionen. Tracing JIT verfolgt typspezialisierte Pfade und ist seit PHP 8.0 der Default.
Konfiguration
opcache.jit=1254, opcache.jit_buffer_size=100M, Hot-Thresholds je nach Workload feinjustieren.
Wann es sich lohnt
CPU-gebundene Workloads: deutlich. I/O-gebundene Webanwendungen: kaum, weil Syscalls nicht beschleunigt werden.
11. FAQ: Der JIT-Compiler in PHP 8
1Was ist der Unterschied zwischen OPcache und dem JIT-Compiler?
2Was bedeutet der Wert 1254 bei opcache.jit?
3Was passiert, wenn opcache.jit_buffer_size zu klein ist?
4Function JIT vs. Tracing JIT?
5Wofür stehen jit_hot_func, jit_hot_loop, jit_hot_side_exit?
6Bringt der JIT-Compiler etwas für DB-lastige Webanwendungen?
7Warum deaktiviert Xdebug den JIT-Compiler?
8Wie messe ich den JIT-Effekt korrekt?
9Gibt es Kompatibilitätsprobleme mit Extensions?
10Sollte ich den JIT-Compiler grundsätzlich aktivieren?
Mironsoft
PHP-Performance-Analyse, Profiling und Infrastruktur-Tuning
Ist der JIT-Compiler für euren Workload überhaupt relevant?
Wir profilieren eure PHP-Anwendung, ermitteln den tatsächlichen Anteil an CPU-gebundener Rechenzeit und konfigurieren opcache.jit gezielt dort, wo es einen messbaren Unterschied macht, statt pauschale Empfehlungen ungeprüft zu übernehmen.
Workload-Profiling
CPU-gebundene vs. I/O-gebundene Anteile eurer Anwendung sauber ermitteln
JIT-Konfiguration
opcache.jit, jit_buffer_size und Hot-Thresholds passend zum Workload dimensionieren
Benchmark-Aufbau
Belastbare Vorher-Nachher-Messungen statt generischer Marketing-Zahlen