PHP Profiler – XDebug
Wer viel mit PHP arbeitet kommt irgendwann zu dem Punkt, dass der PHP Code trotz intensiver Optimierung nach wie vor zu langsam ist. Mit einem Profiler kann man auf einfache Weise effektiv den Flaschenhals (Bottleneck) des ausführbaren Codes finden und dort gezielt die Optimierung intensivieren. Zu diesem Zweck gibt es einige Profiler, ich zeige euch in diesem Artikel wie man mit XDebug, einer Open Source Bibliothek den PHP Code optimieren kann.
Wie installiert man XDebug?
Die vermutlich größte Herausforderung für einen PHP Programmierer ist die Installation von XDebug. Diese ist etwas kompliziert und meiner Meinung nach nicht gut genug dokumentiert. Generell ist XDebug bei PHP nicht dabei. In vielen Artikeln im Internet ist zu lesen, dass XDebug mit PHP auf dem Betriebssystem neu kompiliert werden muss um dort zu funktionieren, eine eigene Bibliothek die man über den Paketmanager installieren kann gibt es nicht.
Meiner Erfahrung nach kommt man am schnellsten mit PECL zu einem funktionierenden XDebug. Die Abkürzung PECL steht für PHP Extension Community Library und ist tatsächlich ein Teil von PEAR, dem Repository für PHP Erweiterungen (Extensions). PECL ist zudem auch das Linux Kommando um eben solche PHP Erweiterungen von PECL zu installieren. Doch bevor man überhaupt damit starten kann muss man PECL am Linux System installieren. Dieses ist Standardmäßig nicht installiert und die Ausführung des Kommandos pecl auf der Kommandozeile liefert folgendes Ergebnis:
Die Anwendung »pecl« ist momentan nicht installiert. Sie können sie durch folgende Eingabe installieren: sudo apt-get install php-pear
Installation von PECL unter Linux
Auf meinem virtuellen Debian Referenzsystem war PECL nicht installiert, aus diesem Grund musste ich es nachträglich installieren. Zusätzlich habe ich auch noch die PHP Developer Bibliothek installiert. Das geht mit dem folgenden Kommando:
apt-get install php5-dev php-pear
XDebug installieren
Mit dem pecl Kommando ist die nachträgliche Installation von XDebug ein Kinderspiel:
pecl install xdebug
XDebug konfigurieren
Obwohl XDebug gerade installiert wurde kann man trotzdem dessen Funktionalität nicht nutzen. PHP Erweiterungen muss man manuell aktivieren. In diesem Fall funktioniert das mit einer zusätzlichen Zeile in der PHP Konfigurationsdatei php.ini. Wo man diese Datei findet ist von System zu System unterschiedlich, bei Debian ist sie in folgendem Ordner zu finden:
cd /etc/php5/apache2 nano php.ini
Mit den beschriebenen Kommandos wechseln wir in den Ordner und öffnen die php.ini Datei in einem Texteditor. Ans Ende der Datei (die php.ini Datei ist sehr lang, also ganz nach unten scrollen) fügen wir folgende 3 neue Zeilen ein:
zend_extension = "/usr/lib/php5/20100525/xdebug.so" xdebug.profiler_output_dir = "/home/benutzername/debug" xdebug.profiler_enable = 1
Die erste Zeile aktiviert bzw. fügt die PHP Extension hinzu. Der angegebene Pfad und die xdebug.so Datei existieren erst seit der Installation von XDebug über pecl. Vermutlich ist der Pfad bei anderen Linux Distributionen anders. Man findet die xdebug.so Datei aber garantiert, wenn man danach sucht! Nach einem Neustart des Webservers hat man bei der Ausführung von PHP Code nun die XDebug Funktionalität. Das erkennt man, da die Fehlermeldungen und Warnhinweise etwas anders formatiert sind und zusätzliche Informationen anzeigen.
Da sich dieser Artikel mit dem Profiler von XDebug beschäftigt habe ich neben dem „Aktivieren“ des Moduls noch zwei zusätzliche Zeilen der php.ini Datei hinzugefügt. Mit xdebug.profiler_enable muss der Profiler manuell aktiviert werden. Das ist deshalb wichtig, da der Profiler mehrere 100 MB an Profilerinformationen abspeichert und man ihn immer nur kurz zum Testen bzw. generieren von Laufzeitinformationen aktivieren sollte.
Mit xdebug.profiler_output_dir legt man ein Verzeichnis fest in dem Profilerinformationen der PHP Skriptausführung gespeichert werden. ACHTUNG: das Verzeichnis muss für den Prozess der PHP Ausführt beschreibbar sein. Ich habe in diesem Beispiel einen Debug Ordner im Home-Verzeichnis meines Benutzers angelegt. Da aber Apache2 nicht über meinen Benutzer aufgerufen war der Ordner anfangs immer leer. Erst nachdem ich volle Schreibrechte mit
chmod 777 /home/benutzername/debug
gesetzt hatte wurden dort Profilerinformationen abgespeichert.
Arbeiten mit dem XDebug Profiler
Die Arbeit mit dem XDebug Profiler ist denkbar einfach. Sofern man alles wie weiter oben beschrieben konfiguriert hat muss man den Profiler in der php.ini lediglich aktivieren (xdebug.profiler_enable = 1) und danach den Webserver neu starten:
service apache2 restart
Jedes Mal wenn nun ein Prozess PHP Code ausführt wird unter Angabe der Prozessnummer als Dateiname die erzeugten Profilerdaten abgespeichert. Mit einigen Seitenaufrufen der PHP Applikation kann man so relativ schnell mehrere 100 MB an Daten generieren. Man sollte also den Profiler sehr sparsam und gezielt verwenden.
Was macht man nun aber mit den erzeugten Ausgaben des Profilers?
Profiler Daten analysieren
Die Daten lassen sich am einfachsten mit einem grafischen Tool analysieren. Das Programm KCacheGrind eignet sich meiner Meinung nach perfekt dafür. Ich habe mir das über den Paketmanager auf meinem Ubuntu System installiert. KCacheGrind ist in der Funktionalität fast selbsterklärend. Man kann die vom Profiler erzeugten Dateien laden und man bekommt von KCacheGrind eine schöne Darstellung über alle PHP Funktionen die aufgerufen, wie lange und vor allem wie oft diese durchlaufen wurden.
Der Screenshot von KCacheGrind zeigt eine meiner Profiler Auswertungen von meinem aktuellen Projekt. Dabei ist recht gut zu erkennen, dass fast 97% der Ausführungszeit (93000 Aufrufe) für Abfragen auf der Datenbank verwendet worden sind. Also ganz klar der Flaschenhals! Die Detailauflistung rechts zeigt, die getSetupOfType Funktion mit lediglich 222 Aufrufen aber fast 90% Ausführungszeit unbedingt optimiert werden muss. In meinem Fall brachte die Änderung eines SQL Befehls eine Laufzeitverbesserung von zuerst über 10 Minuten zu ca. 50 Sekunden.
Fazit
Der XDebug Profiler ist in Verbindung mit einem Analysetool wie KCacheGrind das perfekte Mittel um PHP Code zu optimieren. Man kann recht einfach und zuverlässig Codeteile entdecken die optimiert werden können und somit zu einer Verbesserung der Performance führen. Mehr als Aufspüren von solchen Problemen kann man so aber nicht. Die eigentliche Optimierung des Codes muss man immer noch selbst durchführen. Ein grundlegendes Wissen über Techniken zur Verbesserung der Performance sind also totzdem noch Voraussetzung für einen erfolgreichen Programmierer.