Shopware 6 Performance Blog

Shopware 6 Ladezeit mit PHP OPcache optimieren

Möchte man die Performance seines Shopware 6 Onlineshops optimieren, kommt man bei den PHP-Einstellungen nicht um das Thema OPcache herum. Doch was ist der PHP OPcache eigentlich und welche Vorteile bringt er mit sich?

Einige der Punkte haben wir bereits beim Prüfen der Shopware 6 Performance Tweaks in meinem letzten Beitrag angeschaut. Solltest Du ihn verpasst haben, kannst Du hier nachschauen.

Was ist der PHP Opcache?

Wie viele Wissen, wird PHP im Gegensatz zu anderen Programmiersprachen wie C oder C++ nicht “vorher” kompiliert. Der Code wird bei PHP “on the fly” beim Request interpretiert, was zum einen viel Flexibilität bietet (Anpassungen im Code sind direkt sichtbar), aber gerade auf der Produktiv-Umgebung auch Performance-Einbußungen bedeutet. Bei jedem Aufruf wird unser PHP Code nämlich neu geparst, kompiliert und interpretiert, bis die Anweisung von der CPU ausgeführt werden kann.

Der OPcache soll genau diesem Problem entgegenwirken, um an einer bestimmten Stelle während der Ausführung Code zwischenzuspeichern, damit dieser nicht jedes Mal alle Schritte durchlaufen muss.

Wie funktioniert der Opcache?

Um zu den OPcache genauer zu verstehen, schauen wir uns im ersten Schritt an, wie PHP überhaupt funktioniert und der Code überhaupt ausgeführt wird.

Wird ein Request an unseren Shopware Shop geschickt (z.B. die Startseite), gibt es einen sogenannten PHP Interpreter, der sich um die Ausführung des PHP-Codes kümmert. Vereinfacht gesagt gibt es vier Schritte, welche beim Ausführen durchlaufen werden.

  • Schritt 1 & 2 Lexing & Parsing: Der PHP-Quellcode wird in Tokens zerlegt.
  • Schritt 3 Kompilierung: Aus den Tokens werden sogenannte Opcodes (Bytecode) generiert.
  • Schritt 4 Interpretation: Die Opcodes werden interpretiert und auf der Zend Engine VM ausgeführt

Über den OPcache können Schritt 1 bis 3 übersprungen werden. Der generierte Bytecode aus Schritt 3 (die Opcodes) werden hierbei im OPcache für jedes PHP-Skript im Arbeitsspeicher (RAM) zwischengespeichert, sodass sie bei zukünftigen Requests nur noch aus dem Cache geladen und auf der Zend Engine ausgeführt werden müssen.

opcache garfik

Vorteile von Opcache

Die Vorteile des OPcaches sind deutlich:

  1. Geringere Serverantwortzeit: Da der PHP-Parser und -Compiler bei nachfolgenden Aufrufen von Skripten umgangen werden kann, können Anfragen schneller verarbeitet werden, wodurch unseren Kunden der Onlineshop und deren Inhalte schneller angezeigt wird. Warum das wichtig ist, kannst Du hier nachlesen 🙂
  2. Weniger Serverauslastung: Durch die Reduzierung des Overheads für die Interpretation des PHP-Codes wird die CPU weniger belastet, was die Server-Ressourcen schont. Gerade bei Shops mit viel Traffic sorgt das dafür, dass der Server weiterhin stabil läuft.
  3. Geringere Hostingkosten: Durch die geringere Auslastung können bei gleicher Hardware mehr Anfragen verarbeitet werden. Dadurch spart man sich automatisch auch unnötige Kosten beim Hoster und kann besser “nach oben” skalieren

PHP Opcache installieren und aktivieren

Die meisten Entwickler/ Agenturen kümmern sich oft nicht selbst um das Hosting der Online-Shops, sondern beauftragen einen Hosting-Dienstleister. Wenn Ihr mit einem Hoster zusammenarbeitet, würde ich empfehlen, die Einstellungen in der php.ini abzusprechen. Ggf. kann der Hoster Euch auch ein paar für Euer Setup individuelle Empfehlungen aussprechen.

Opcache ist in neueren PHP-Versionen (ab PHP 5.5) standardmäßig integriert, muss aber aktiviert und konfiguriert werden. Bei den “guten” Hostern ist das meistens bereits der Fall. Sicherheitshalber empfehle ich aber jedem, einmal nachzuschauen. Die folgenden Schritte zeigen, wie Du Opcache prüfst und ggf. aktivierst.

1. Überprüfen, ob Opcache aktiviert ist:

Am einfachsten ist es, wenn Du eine phpinfo.php im public-Ordner Deines Shops erstellst und über den Browser öffnest. Dort suchst Du nach dem Abschnitt “Zend OPcache” und stellst sicher, dass “Opcode Caching” auf “Up and Running” steht.

phpinfo opcache

Solltest Du in der Konsole nachschauen wollen, kannst Du es mit folgendem Befehl prüfen:

php -v

Wenn Opcache aktiviert ist, siehst Du eine Ausgabe wie:

PHP 8.3.6 (cli) (built: Jun 13 2024 15:23:20) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.6, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.6, Copyright (c), by Zend Technologies

2. Aktivierung in der php.ini

Falls Opcache nicht aktiviert ist, kannst Du ihn in der php.ini-Konfigurationsdatei aktivieren. Hier eine Beispiel-Konfiguration:

zend_extension=opcache
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.fast_shutdown=1

3. Server neu starten

Nach der Aktivierung von Opcache musst Du den Webserver (Apache, Nginx oder ein anderer) neu starten, damit die Änderungen wirksam werden:

sudo service apache2 restart
# oder
sudo service nginx restart

OPcache Konfiguration optimieren

Die richtige Konfiguration von Opcache hängt von den spezifischen Anforderungen Deines Shopware 6 Shops und der verfügbaren Server-Ressourcen ab. Hier sind die unserer Meinung nach wichtigsten Einstellungen für den OPcache:

opcache.memory_consumption

Die Einstellung opcache.memory_consumption gibt an, wie viel Arbeitsspeicher der OPcache belegen darf. Je nachdem wie viel Code Du hast, kann diese Einstellung anders bei Dir aussehen. Für viele unserer Shopware 6 Kunden reicht eine Größe von ca. 4GB aus. Mit einem OPcache-GUI-Tool wie hier kannst Du im Prod-Betrieb prüfen, wie viel Speicher belegt ist und welche Skripte er enthält. Damit kannst Du sehen, wenn der OPcache voll ist und entweder nicht benötigte Skirpte über “opcache.blacklist_filename” ausschließen oder entsprechend den Speicher erhöhen.

opcache.memory_consumption=4096M

opcache.interned_strings_buffer

Neben dem Bytecode (die oben erwähnten Opcodes) kann der OPCache auch sogenannte „interned PHP Strings“ im RAM zwischenspeichern. Das reduziert den Speicherbedarf bei jedem Request und verbessert so die Performance. Damit der OPcache optimal arbeitet, sollte er niemals komplett ausgelastet sein. Der Standardwert liegt bei 8MB, aber für Shopware wird empfohlen, diesen auf mindestens 20MB zu erhöhen. In dieser Einstellung wird der Speicherplatz in MB festgelegt, den PHP für diese Strings reserviert. Über das GUI-Tool kannst Du auch hier im Prod-Betrieb die Auslastung prüfen und sie entsprechend erhöhen.

opcache.interned_strings_buffer=20

Revalidate Frequency

Der OPcache prüft die gecachten PHP-Dateien auf Änderungen, um sie bei Bedarf neu zu kompilieren & zu cachen. Je seltener Opcache die Dateien überprüft, desto schneller ist der Zugriff. In Entwicklungsumgebungen solltest Du einen niedrigeren Wert verwenden (z.B. opcache.revalidate_freq=0), um Änderungen sofort zu sehen. In Produktionsumgebungen kann dieser Wert jedoch höher sein, um die Performance zu maximieren (wir empfehlen mindestens 60).

opcache.revalidate_freq=60

opcache.validate_timestamps

Für maximale Performance kann man das oben angesprochene Revalidieren auch ganz deaktivieren. Hierfür opcache.validate_timestamps=0 konfigurieren. Damit muss man bei einem Deployment zwar den OPcache manuell leeren, was durch den Performance-Vorteil aber aus unserer Sicht gerade bei größeren Shops gerechtfertigt ist.

opcache.validate_timestamps=0

opcache.enable_file_override

Diese Einstellung sorgt dafür, dass der OPcache für PHP-Funktionen wie file_exists und is_file genutzt wird. Das ist besonders cool, weil diese Funktionen bei Shopware unter anderem oft beim Template-Rendering benutzt wird. Der OPcache sorgt dann dafür, dass Dateisystemabfragen nicht immer wieder neu ausgeführt werden müssen, was die Performance erheblich verbessert.

opcache.enable_file_override=1

OPcache preload

Mit PHP 7.4 wurde der OPcache mit einer neuen Funktionalität erweitert: Preloading.

In meinem letzten Beitrag hatte ich bereits etwas über das Feature gesprochen. Vereinfacht gesagt können damit PHP-Dateien im Arbeitsspeicher vorabgeladen werden und während der gesamten Laufzeit des Webservers verfügbar gehalten werden.

Die Ladezeiten verbessern sich entsprechend deutlich, weil vorkompilierter Code nicht bei jedem Aufruf von der Festplatte geladen werden muss und damit weniger Disk-I/O und Parsing-Overhead anfällt. Gerade bei Frameworks oder großen Codebasen, die viele Klassen wiederverwenden, ist das vorteilhaft.

Shopware 6 erstellt dazu eine opcache-preload.php im Cache-Ordner, die man in der php.ini einbinden kann. Sobald der Webserver (sei es Apache oder Nginx) startet, lädt der OPCache diese Datei vor, kompiliert sie einmalig und hält sie effizient während der gesamten Laufzeit bereit.

Wichtig: Preloading funktioniert nur mit persistenten PHP-Prozessen wie FPM (FastCGI Process Manager) oder mod_php in Apache. Bei einfachen PHP-Skripten, die ohne solche Prozesse ausgeführt werden (z. B. über die Kommandozeile), ist Preloading nicht sinnvoll.

Laut Shopware bringt Preloading einen Performance-Boost von etwa 2-5%. Der Vorteil liegt also auf der Hand. Der Nachteil? Wenn Änderungen an PHP-Dateien (z.B. ein Deployment) vorgenommen werden, muss der Server oder der PHP-FPM-Prozess neu gestartet werden, damit die Änderungen wirksam werden.

In meinem Testshop musste ich als User www-data verwenden. Auch der Pfad zur preload-Datei kann bei jedem Hoster anders aussehen.

opcache.preload=/var/www/html/var/cache/opcache-preload.php
opcache.preload_user=nginx

Ladezeiten-Test (Shopware 6 Shop)

Zum Testen habe ich mir einen frischen Shopware 6 Shop bei Hetzner mit einem LAMP-Stack aufgesetzt. Schau gerne vorbei: shop.pagespeedy.de. Der Shop läuft auf Apache2, PHP 8.3 und MySQL 8.0. Zu Beginn sind natürlich die Standardeinstellungen aktiv gewesen. Um die Performance zu messen, nutze ich das PHP-Profiling Tool Tideways.

Für den Test habe ich mich dazu entschieden, die Kategorieseite im ungecachten Zustand aufzurufen – einmal mit und einmal entsprechend ohne konfiguriertem OPcache. Danach rechne ich den Durchschnitt der TTFB (Time to First Byte) aus.

Ergebnis

Ohne den OPcache liegt die Ladezeit im Listing aktuell bei ca. 650ms. Laut Tideways macht das Kompilieren einen Großteil der TTFB aus. Selbst gecacht liegt sie bei 110ms!

Baue ich den OPcache wieder ein, zusammen mit allen anderen Optimierungen (validate_timestamps aus, enable_file_override an, preloading), liegt die TTFB nur noch bei ca. 315ms. Eine deutliche Verbesserung. Im gecachten Zustand sind es auch nur noch ca. 16ms!

Fazit

PHP Opcache ist ein mächtiges Werkzeug, um die Leistung Deines Shopware 6 Onlineshops deutlich zu steigern. Durch das Caching des kompilierten Bytecodes wird der Overhead bei der Ausführung von PHP-Skripten reduziert, was zu schnelleren Ladezeiten, einer geringeren Serverlast und einer verbesserten Benutzererfahrung führt.

Mit den richtigen Konfigurationseinstellungen kannst Du das volle Potenzial von Opcache ausschöpfen und deine PHP-Anwendungen für die Zukunft optimieren.

Ich würde den OPcache daher jedem Entwickler stark empfehlen legen 🙂

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert