Warum die deutsche Sprachdatei WordPress um 44 Prozent langsamer macht
Jeder deutschsprachige WordPress-Anwender kennt vermutlich diese kurze PHP-Zeile:
define ('WPLANG', 'de_DE');
Mit dieser einen Zeile wird WordPress deutschsprachig – und jeder Seitenaufruf rund 44 Prozent langsamer.
Im Folgenden zeige ich, warum dieser Performance-Einbruch eintritt und welche Möglichkeiten existieren, dem entgegenzuwirken.
Warum kann WordPress Deutsch?
WordPress verwendet im gesamten Code englische Originaltexte. Zur Lokalisierung der Software in anderen Sprachen muss WordPress Übersetzungen aus zusätzlichen Dateien im verbreiteten PO-Format einlesen. Die deutschsprachige Lokalisierung von WordPress 3.1.x enthält fast 3.200 Textschnippsel für den WordPress-Kern und 87 Übersetzungen für das Theme „TwentyTen“. Je nach Konfiguration kommen dann noch lokalisierte Texte der aktiven Plugins dazu.
Was kostet Zeit?
Ziemlich früh bei jedem Request wird innerhalb von wp-settings.php
die Funktion load_default_textdomain() aufgerufen.
Über ein paar weitere Aufrufebenen erreicht WordPress dann import_from_reader(), die tausende kurzer Textschnippsel aus der Sprachdatei des WP-Cores einliest. Wenig später ruft das Theme „TwentyTen“ über den Wrapper load_theme_textdomain()
ein zweites Mal import_from_reader()
auf, um die Übersetzungen der Theme-Texte zu laden.
Die lokalisierten Texte werden für jeden Aufruf der öffentlichen Website, bei jeder Aktion im Backend, bei jedem AJAX-Request und bei der Generierung der XML-Feeds geladen. load_default_textdomain()
verbraucht nach meinen Messungen etwa 30 bis über 50 Prozent der gesamten Zeit, die für die Bearbeitung eines Requests nötig ist.
Zusammengefasst heißt das: Ein deutschsprachiges Blog ist für menschliche Besucher, Googlebot und Administratoren wesentlich langsamer als das exakt gleiche Blog auf einem englischen WordPress.
Messmethode
Zur Auswertung der Laufzeit-Unterschiede zwischen der deutsch- und der englischsprachigen Variante habe ich eine lokale WordPress-Installation mit Xdebug vermessen und die so gewonnenen Profiling-Daten für folgende drei Requestrouten mit webgrind visualisiert:
- Darstellung von zehn einfachen Posts auf der Blog-Homepage mit dem Standardtheme „TwentyTen“
- Aufruf der Dashboard-Übersicht im Backend
- Darstellung des RSS-Feeds
Der Testaufbau bestand aus:
- WordPress 3.2-bleeding r17633
- Theme „TwentyTen“ 1.1
- Keine aktiven Plugins
- Lokaler Webserver ohne Last
- Apache 2.2.9
- PHP 5.2.6
- MySQL 5.0.67
- Xdebug 2.1.1
- webgrind 1.1
- Windows 7 SP1
Messergebnisse
Die Zeit, die WordPress benötigt, um einen einzelnen Request zu erfüllen, variiert je nach Route (Frontend, Backend, RSS). In jedem Fall verschlechtert der Wechsel auf die deutsche Sprachdatei die Geschwindigkeit um zweistellige Prozentsätze.
Für die Darstellung der Frontpage mit zehn Blogbeiträgen benötigt die deutsche Fassung fast doppelt so lange wie das englische Pendant, das Backend wird um etwa ein Drittel gebremst und die RSS-Feeds werden über 60% langsamer erzeugt.
Der Webgrind-Report liefert die Laufzeiten jeder einzelnen Funktion, die WordPress zur Generierung der Frontpage aufruft. Sehr schön sieht man hier, dass MO->make_entry() für jedes einzelne Textschnippsel ein Mal aufgerufen wird. 3.273 übersetzte Texte werden in 618 ms geladen.
Man erkennt deutlich, dass gerade die Lokalisierungsfunktionen aus der POMO-Bibliothek den Löwenanteil der Zeit verbrauchen.
Mit MO->import_from_reader
, MO->make_entry
, Translation_Entry->key
und POMO_REader->substr
sind vier der fünf zeitaufwändigsten Funktionen bei jedem Seitenaufruf für die deutsche Übersetzung nötig. Es gilt ein annähernd linearer Zusammenhang: Je mehr übersetzte Texte, desto höher der Zeitbedarf.
Der selbe Ablauf in der englischsprachigen Variante sieht zum Vergleich so aus:
Ein ähnliches Verhältnis ergibt sich auch für das Backend und Feeds.
Die Messung eines Profiling-Durchlaufs auf meinem Testsystem ergab diese in weiteren Durchläufen recht gut reproduzierbaren Laufzeiten:
Route |
Laufzeit [en] |
Laufzeit [de] |
Relative Leistung [de] |
Frontend |
2343 ms |
4327 ms |
56% |
Backend |
3003 ms |
4283 ms |
70% |
RSS-Feed |
1129 ms |
2952 ms |
38% |
Diese Zahlen sollte man auf jeden Fall mit ein wenig kritischer Distanz werten: Ich habe Messungen auf einem einzigen System durchgeführt und auf einem zweiten Rechner auf Plausibilität geprüft. Ergebnisse mit Webspace auf anderen Betriebssystemen oder Dateisystemen können abweichen, und ich würde sehr gerne Zahlen von Apple- oder Linux-Systemen zum Vergleich sehen. Trotzdem glaube ich, dass das Lokalisierungspackage in WordPress einen merklichen Anteil an der Performance einer WordPress-Site hat.
In der grafischen Darstellung wird deutlich, wie eklatant der Leistungseinbruch der deutschen Fassung ausfällt:
Verbesserungspotential
Was kann man tun, um diesen Klotz am Bein los zu werden? Leider habe ich dazu keine ideale Lösung, sondern nur ein paar Denkansätze:
Ein Frontend-Cache ist immer nützlich und hilft auch hier. Die negativen Auswirkungen der Lokalisierung im Backend lindert ein Cache aber nicht.
Eine weitere Möglichkeit wäre, auf die deutsche Sprachdatei komplett zu verzichten. Im Backend findet man sich eventuell auch auf Englisch zurecht, und für das Frontend setzt man einfach ein Theme ein, dass auch ohne Lokalisierung Deutsch spricht.
Drittens könne man einen Vorteil aus der Tatsache ziehen, dass der Leistungseinbruch mit der Zahl der übersetzten Texte zusammenhängt, und eine auf das Wesentliche verkürzte deutsche Sprachdatei einsetzen. Ein radikaler Löschkreuzzug in der Sprachdatei, dem ein paar hundert Hilfetexte oder unbenutzte Texte für WP-Multisite zum Opfer fallen, ist mit Hilfe von Poedit . Die Ladezeit sinkt mit jedem entfernten Eintrag in der Sprachdatei um etwa 0,3 Promille.
Weitere Verbesserungen erfordern, dass seitens der WordPress-Programmierer an der Optimierung der POMO-Bibliothek selbst gearbeitet wird und zum Beispiel persistente Caches für die translation entries genutzt werden. Das Trac-Ticket dafür gibt es schon…
Fußnoten