Drupal-Performance-Odysee mit Happy-End

Mit dem Update unseres Intranet-Portals von D5 auf D6 und dem gleichzeitigen Umzug der Installation von einem virtuellen Webserver (Xen+Linux) auf einen physischen Server (auch Linux, identische Hardware) handelte ich mir einen totalen Einbruch der Performance der Seite ein. Ein “normaler” Seitenaufruf dauerte ~7 Sekunden, für die Startseite (mit Panels voller Views-Blöcke) dauerte das Laden ~13 Sekunden. Somit war das Intranet-Portal praktisch unbenutzbar.

Nachdem ich mich von dem schrecken erholt hatte, begann ich mit der Ursachenforschung.

Den Einstieg bekam ich mit Ingos Blog-Eintrag.

Von dort ging es weiter zu https://2bits.com/articles/drupal-performance-tuning-and-optimization-for-large-web-sites.html und dem sichten der extra-langen Liste nach anwendbaren Vorschlägen.

Mein erster Kandidat war die MySQL-Datenbank. Sie läuft auf dem selben Rechner wie der Web-Server also keine zu überprüfende Netzwerk-Kommunikation. Also nahm ich das tuning-primer.sh-Skript und
optimierte den DB-Server, so lange mir die Vorschläge plausibel erschienen und endlich alle Tests auf Grün standen. Keine Verbesserung.

Auch zeigte das devel.module, dass nur ein Bruchteil der Ladezeit für die SQL-Queries benötigt wurde.

Als nächstes (wenige Tage später) nahm ich mir den Apache vor. Auf ihm laufen neben PHP-Skripten (drupal, phpmyadmin) auch diverse Python-Apps und ein Scalix mit Tomcat-Servlet-Connector. Ich entfernte alle Apache-Erweiterungen, die nicht
unbedingt benötigt werden (z.B. mod_userdir und mod_info). Dann noch .htaccess-Konfigurationen in die statische Server-Konfiguration übernommen und eaccelerator installiert. Keine Verbesserung.

Zwischendurch habe ich ein Benchmark eingeschoben, um von der “gefühlten” Trägheit des Servers zu vergleichbaren Werten zu kommen und vielleicht schon kleine Verbesserungen wahrnehmen zu können.

Das Ergebnis:

# ab -n50 -c2 -dS http://portal.firma.de/node/111
...
Connection Times (ms)
              min   avg   max
Connect:       49   105   302
Processing: 11182 12339 16441
Total:      11231 12444 16743

Frustrierend!

Ich hatte als nächstes den verdacht, dass der Apache (2.0.18) mit der Multifunktionalität zu kämpfen hat und nicht gleichzeitig ein guter PHP- und Servlet-Host sein kann. Außerdem wollte ich mal lighttpd und FastCGI testen, weil das bei vielen Performance-Reports als Alternative genannt wird (unabhängig von einander). So hatte ich lighttpd+FastCGI
auf Port 81 installiert und auf die identische Code-Basis losgeschickt. Der Benchmark ergab: Keine Verbesserung.

Nun, nach ein paar weiteren Bedenk-Tagen bin ich zu der festen Überzeugung gekommen, dass das Problem im Drupal zu finden war. So habe ich nach weiterem Literaturstudium hatte ich dann
den entscheidenden Tipp gefunden: http://civicactions.com/blog/2009/feb/10/profiling_drupal.

So kopierte ich die gesamte Drupal-Installation auf mein Notebook (zur Vereinfachung der ganzen Sache), installierte “xdebug“http://www.xdebug.org/, aktivierte das Generieren von Profiling-Informationen und installierte kcachegrind (KDE, Linux). Und ziemlich schnell war klar, dass der Performance-Engpass durch das Modul og_content_type_admin verursacht wurde, welches in hook_init jedes mal die Funktion “menu_router_rebuild” aufruft. Als ich diesen Aufruf testweise auskommentierte, hatte ich kein Performance-Problem mehr!

Ein nochmaliger Benchmark lieferte überzeugende Ergebnisse:

# ab -n50 -c2 -dS http://portal.firma.de/node/111
...
Connection Times (ms)
              min   avg   max
Connect:       90   105   148
Processing:  1279  1470  2139
Total:       1369  1575  2287

Mit 1,5 Sekunden Seiten-Ladezeit kann ich sehr gut leben 🙂

Das Problem ist den Entwicklern übrigens bekannt, allerdings ist das Ticket geschlossen und die vorgeschlagene Lösung hat bei mir keine Verbesserung gebracht. So habe ich mich von der Funktionalität leichten Herzens getrennt.

Screenshot KCachegrind