Zend OPcache: Konzept, Installation und Konfiguration mit den php.ini-Werten und dem Deaktivieren von JIT
Zend OPcache ist eine PHP-Erweiterung, die PHP-Skripte zu Bytecode kompiliert und im Shared Memory ablegt, sodass das Kompilieren beim nächsten Ausführen derselben Datei entfällt. Als nach dem Aktivieren von JIT auf einem WordPress-Server mit PHP 8.3 auf allen Seiten ein 500-Fehler auftrat, wurde der Server wiederhergestellt, indem OPcache unverändert blieb und nur JIT deaktiviert wurde.
Seit PHP 5.5 wird OPcache standardmäßig mit PHP ausgeliefert.
1️⃣ Konzept von Zend OPcache: Bytecode-Caching
Bei jeder Anfrage durchläuft ein PHP-Skript drei Schritte: Datei lesen, zu Bytecode kompilieren und ausführen. Ist OPcache aktiv, entfallen ab der zweiten Anfrage für dieselbe Datei die ersten beiden Schritte, und es bleibt nur das Ausführen.
Das Shared Memory, in dem OPcache den Bytecode ablegt, wird von allen Workern von PHP-FPM gemeinsam genutzt. Sind mehrere Websites mit demselben PHP-FPM verbunden, liegen auch deren Skripte in einem gemeinsamen Shared Memory.
OPcache speichert kompilierten PHP-Code, deshalb finden PHP-Ausführung und Datenbankabfragen bei jedem Seitenaufruf weiterhin statt. Die PHP-Ausführung ganz zu überspringen, indem fertiges HTML gespeichert wird, ist die Aufgabe eines Seitencaches.
2️⃣ Installation von PHP OPcache prüfen
Ob OPcache installiert ist, siehst du in der letzten Zeile der Ausgabe von [php -v].
php -vPHP 8.3.22 (cli) (built: Jun 3 2025 17:17:57) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.3.22, Copyright (c) Zend Technologies
with Zend OPcache v8.3.22, Copyright (c), by Zend TechnologiesFehlt die letzte Zeile, installiere das Paket mit dnf. Der Paketname lautet meist php-opcache; wurden aus dem Remi-Repository mehrere PHP-Versionen nebeneinander installiert, hängt die Version daran, etwa php83-php-opcache.
dnf -y install php-opcacheDas Paket php-opcache aus dem Remi-Repository lädt die Erweiterung über die Zeile [zend_extension=opcache] in [/etc/php.d/10-opcache.ini]. Starte PHP-FPM nach der Installation neu, damit OPcache auch für Webanfragen gilt.
3️⃣ OPcache-Konfiguration: php.ini-Werte
Die OPcache-Einstellungen können an zwei Stellen stehen: im Abschnitt [opcache] von [/etc/php.ini] und in [/etc/php.d/10-opcache.ini].
php --iniConfiguration File (php.ini) Path: /etc
Loaded Configuration File: /etc/php.ini
Scan for additional .ini files in: /etc/php.d
Additional .ini files parsed: /etc/php.d/10-opcache.ini,Dateien im Ordner php.d werden nach der php.ini gelesen. Steht derselbe Eintrag an beiden Stellen, gilt daher der Wert aus php.d.
Die folgende Tabelle zeigt die Standardwerte von PHP 8.3 und die Werte, die auf dem geprüften WordPress-Server gelten.
| Kategorie | Standardwert in PHP 8.3 | Angewendeter Wert | Bedeutung |
|---|---|---|---|
| opcache.enable | 1 | 1 | OPcache verwenden |
| opcache.enable_cli | 0 | 1 | Auch in PHP auf der Kommandozeile verwenden (wp-cli usw.) |
| opcache.memory_consumption | 128 | 1024 | Shared Memory, in dem der Bytecode liegt (MB) |
| opcache.interned_strings_buffer | 8 | 16 | Speicher, der gleiche Zeichenketten nur einmal ablegt (MB) |
| opcache.max_accelerated_files | 10000 | 10000 | Obergrenze für die Zahl der cachebaren Schlüssel (die tatsächliche Grenze ist eine Primzahl ab diesem Wert: 16229 bei 10000) |
| opcache.max_wasted_percentage | 5 | 10 | Wenn der Speicher knapp wird und der verschwendete Platz diesen Anteil übersteigt, wird der Cache geleert und neu gestartet |
| opcache.validate_timestamps | 1 | 1 | Prüfen, ob sich Dateien geändert haben |
| opcache.revalidate_freq | 2 | 60 | Wie oft auf Dateiänderungen geprüft wird (Sekunden) |
| opcache.jit | tracing | disable | JIT-Modus (ab PHP 8.4 ist der Standardwert disable) |
| opcache.jit_buffer_size | 0 | 0 | JIT-Speicher; bei 0 läuft JIT nicht (ab PHP 8.4 ist der Standardwert 64M) |
Die Werte im Abschnitt [opcache] der [/etc/php.ini] sind unten aufgeführt. Die Speichergröße richtet sich nach dem Arbeitsspeicher des Servers, [opcache.max_accelerated_files] nach der Zahl der WordPress-Dateien.
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=1024
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=1
opcache.revalidate_freq=60Wird in der php.ini erneut eine Zeile [zend_extension] eingetragen, wird die Erweiterung zweimal geladen, und es erscheint die Warnung [Cannot load Zend OPcache].
Bei [opcache.revalidate_freq] von 60 kann nach dem Ändern einer PHP-Datei noch bis zu 60 Sekunden lang der alte Code laufen.
Auf einem WordPress-Server, auf dem sich PHP-Dateien oft ändern, lässt du [opcache.validate_timestamps] auf 1, damit Dateiänderungen geprüft werden. Die 0, die die Symfony-Dokumentation für Produktivserver empfiehlt, passt zu Servern, auf denen sich PHP-Dateien nur beim Ausrollen einer neuen Version ändern.
Auch bei [opcache.validate_timestamps] auf 0 leert WordPress selbst den Cache der geänderten Dateien, wenn du im Administrationsbereich ein Update machst. Aktualisierst du dagegen mit wp-cli oder änderst Dateien per SSH, läuft der alte Code weiter, bis PHP-FPM neu gestartet wird.
4️⃣ JIT von OPcache deaktivieren
Der JIT-Compiler von PHP 8 beschleunigt rechenintensive Aufgaben, daher bringt er bei einer Anwendung wie WordPress, die Webanfragen bearbeitet, wenig. Auch in der WordPress-Messung im PHP-JIT-RFC schaffte der Lauf mit aktiviertem JIT 326 Anfragen pro Sekunde, der Lauf mit deaktiviertem JIT 315.
Auf einem WordPress-Server mit PHP 8.3.22 wurde JIT mit [opcache.jit=tracing] und [opcache.jit_buffer_size=128M] aktiviert. Drei Tage später, an einem Tag, an dem ein Ansturm von Anfragen die Worker von PHP-FPM mehrmals neu starten ließ, trat auf allen Seiten ein 500-Fehler auf.
Im Fehlerprotokoll stand die Meldung [Allowed memory size of 1073741824 bytes exhausted]. Das darauf folgende [tried to allocate 4295229440 bytes] zeigt den Versuch, bei einem PHP-Speicherlimit von 1 GB auf einmal 4 GB zu reservieren. Nach dem Deaktivieren von JIT wurden dieselben Anfragen normal verarbeitet.
JIT wird deaktiviert, indem die beiden folgenden Zeilen in [/etc/php.d/10-opcache.ini] eingetragen werden. Auch wenn in [/etc/php.ini] noch JIT-Einstellungen stehen, gelten die Werte dieser Datei.
opcache.jit=disable
opcache.jit_buffer_size=0In PHP 8.3 ist der Standardwert von [opcache.jit_buffer_size] gleich 0, JIT läuft also nicht, solange du es nicht gesondert einstellst. Ab PHP 8.4 ist auch der Standardwert von [opcache.jit] gleich disable.
5️⃣ Konfiguration anwenden und prüfen
Geänderte Einstellungen gelten erst nach einem Neustart von PHP-FPM.
systemctl restart php-fpmNach dem Neustart wird das Shared Memory von OPcache geleert und mit den neuen Einstellungen neu zugewiesen.
php -i | grep -E '^opcache\.(enable|memory_consumption|revalidate_freq|validate_timestamps|jit) 'opcache.enable => On => On
opcache.jit => disable => disable
opcache.memory_consumption => 1024 => 1024
opcache.revalidate_freq => 60 => 60
opcache.validate_timestamps => On => OnDie von [php -i] ausgegebenen Werte sind die Einstellungen von PHP auf der Kommandozeile. Auf RHEL-Systemen liest PHP-FPM dieselben Dateien [/etc/php.ini] und [/etc/php.d], daher sind die Werte gleich.
Wenn du [opcache_get_status()] auf der Kommandozeile aufrufst, werden 0 gecachte Skripte angezeigt. PHP auf der Kommandozeile legt bei jedem Lauf ein neues Shared Memory an, daher prüfst du die Auslastung von PHP-FPM, indem du die folgende Datei in den Web-Dokumentordner legst und im Browser öffnest.
<?php
header('Content-Type: text/plain');
$s = opcache_get_status(false);
print_r($s['memory_usage']);
print_r($s['opcache_statistics']);
print_r($s['interned_strings_usage']);
var_dump($s['cache_full']);Ist [cache_full] gleich true, sind das Shared Memory oder die Schlüssel voll. Lösche diese Datei gleich nach der Prüfung.
Auf einem Server, auf dem drei WordPress-Websites dasselbe PHP-FPM nutzen, waren von 1024 MB Shared Memory 317 MB belegt. Es gab pro Website 3.366 bis 4.222 gecachte Skripte, insgesamt 11.358.
OPcache speichert Skripte unter ihrem tatsächlichen Pfad und legt für Dateien, die über einen relativen Pfad geladen werden, einen weiteren Schlüssel mit angehängtem Arbeitsverzeichnis an, deshalb ist die Zahl der Schlüssel größer als die der Skripte. Bei 11.358 Skripten war die Obergrenze von 16.229 Schlüsseln erreicht, und auch der String-Puffer mit 16 MB hatte keinen freien Platz mehr.
Sind die Schlüssel voll, werden neue Skripte nicht gecacht und bei jeder Anfrage kompiliert. Innerhalb von 5 Minuten und 21 Sekunden stiegen die Cache-Misses von 18.408 auf 36.027, die Zahl der gecachten Skripte blieb aber bei 11.358.
Auf einem Server mit mehreren WordPress-Installationen oder vielen Plugins setzt du [opcache.max_accelerated_files] großzügig, damit die Schlüsselgrenze nicht erreicht wird. Bei 20000 liegt die tatsächliche Schlüsselgrenze bei 32.531. Ist der String-Puffer voll, erhöhst du auch [opcache.interned_strings_buffer].
🔢 FAQ & empfohlene Inhalte
Cache
Was ist Cache? Definition und alle Bereiche, in denen Caching genutzt wird
Ein Beitrag, der die Bereiche gliedert, in denen Caches genutzt werden, darunter OPcache, der kompilierten PHP-Code speichert, und der Seitencache, der fertiges HTML speichert.
PHP-FPM
php-fpm max_children-Warnung: Vor dem Aufstocken der Worker die Ursache in den Logs finden
Ein Beitrag, der anhand der Logs die Ursache der Warnung bestimmt, die erscheint, wenn alle PHP-FPM-Worker belegt sind, die sich das Shared Memory von OPcache teilen.
PHP-FPM
Was ist PHP-FPM | PHP-FPM installieren und einrichten
Ein Beitrag zur Installation von PHP-FPM, in dem OPcache läuft, zur Pool-Konfiguration in der www.conf und zum Neustart.
ℹ️ Affiliate-Hinweis
Die Inhalte dieser Website enthalten Affiliate-Links. Kauft ein Besucher über einen dieser Links ein Produkt oder eine Dienstleistung, erhält die Website vom Verkäufer eine Provision. Der Betrag, den der Käufer zahlt(bei Aktionsrabatten sinkt er ↓), steigt dadurch nicht. Angegebene Preise, Rabatte und Lagerbestände entsprechen dem Stand bei Erstellung und können abweichen; prüfe sie daher vor dem Kauf beim Verkäufer. Produkte werden nach eigenen Kriterien ausgewählt und bewertet, und Provisionen beeinflussen weder die Reihenfolge noch den Inhalt der Bewertungen.