Sonntag, 12. Februar 2012


Artikel

Januar 2010 | Artikel

Software-Profiling in PHP

(Link zum Artikel: http://www.entwickler.de/php/artikel/2832)

Wo drückt denn der Schuh?

Text: Nils Langner und Mike Lohmann
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
PHP-Projekte sind sehr oft fragile Systeme. In großen Projekten kann es durchaus vorkommen, dass die gesamte Anwendung langsamer wird, nur weil man an einem kleinen Schräubchen gedreht hat. Diese Änderung lässt in den meisten Fällen natürlich nicht darauf schließen, warum die Performance beeinträchtigt wurde. Vielleicht verändert sie den Pfad durch den Programmcode so, dass nun eine sehr kostspielige Funktion häufig aufgerufen wird. Vielleicht aber auch nicht. Kritische Stellen im Sourcecode zu finden, kann ohne die nötigen Werkzeuge schnell zu einer Sisyphosarbeit werden. Die effektivsten Hilfsmittel zum Lösen dieser Probleme sind Profiler.
Teil 1   Teil 2   Teil 3   

Profiler haben die Aufgabe, den Programmfluss zur Laufzeit zu analysieren. In den meisten Fällen sammeln sie dabei Daten über aufgerufene Methoden, Anzahl der Aufrufe, Dauer der einzelnen Calls, Speicherverbrauch und natürlich den Weg durch den Sourcecode. Eine Untersuchung dieser Kennzahlen erhöht die Chance, kritische Stellen im Code zu finden und existierende Schwachstellen zu beseitigen. Die Funktionsweise von Profilern ist dabei immer gleich. Sie werden als PHP-Erweiterung installiert und klinken sich in den Interpreter ein. Dort verankert, speichern sie alle Informationen, die sie benötigen, um später ein Profil über den Ablauf zu erstellen. Wie man einen Profiler zum Laufen bringt, wie man ihn verwendet und wie man das erstellte Profil interpretiert, soll Teil dieses Artikels sein. Als PHP-Entwickler hat man das Glück, gleich unter mehreren guten Profilern wählen zu können. Wir werden in unseren Beispielen Xdebug, Version 2.0 von Derick Rethans verwenden, da dieser lange Zeit als Quasistandard galt und sich auch heute noch sehr hoher Beliebtheit erfreut. Vorteil des Tools ist auch die zusätzliche Funktionalität, die es mit sich bringt. Neben der Möglichkeit, Profile zu erstellen, wird auch eine Debugging-Schnittstelle geschaffen, die problemlos in alle gängigen Entwicklungsumgebungen integriert werden kann. Ein weiteres Feature ist die erzeugte Statistik zur Codeabdeckung (Code Coverage), die zum Beispiel in Tools wie PHPUnit Einzug findet. Dieser Artikel kann leider nicht all diese Funktionalitäten behandeln, beschränkt sich deshalb auf den Profiling-Teil.

Installation
Die Installation von Xdebug erfolgt am Einfachtsten über PECL. In einem Linux-Betriebssystem mit installiertem PHP und Apache kann man folgenden Befehl zur Installation verwenden: pecl install xdebug. Bei der Installation über PECL wird Xdebug gegen PHP kompiliert. Es kann sein, dass die PHP-Sourcen fehlen. Sollte das der Fall sein, wird die Xdebug-Installation abbrechen. In diesem Fall sollte man die Source-Pakete der verwendeten Linux-Distribution nachladen, oder im Fall von XAMPP das Source.tgz. Nach der erfolgreichen Installation ist eine Anpassung der php.ini notwendig. Manchmal können in einer PHP-Umgebung mehrere php.ini-Dateien angelegt sein. Daher lohnt es sich, über phpinfo herauszufinden, welche php.ini gerade genutzt wird. Dazu kann man einfach folgenden Befehl an der Kommandozeile eingeben: php -i | grep -i php.ini. Dabei sollte dann etwas Ähnliches wie das Folgende angezeigt werden:

  1. Configuration File (php.ini) Path => /opt/lampp/etc
  2. Loaded Configuration File => /opt/lampp/etc/php.ini

Man weiß jetzt, dass die verwendete php.ini in /opt/lampp/etc/ liegt und kann sie editieren. Wenn die PHP-Version >= 5.3.0 ist oder PHP als CLI, CGI oder im Apache MPM Prefork gestartet wird: zend_extension="/xdebug.so". Und wenn die PHP-Version < 5.3.0 ist und PHP in einem Thread gestartet wird (z. B. als ISAPI oder im Apache MPM Worker): zend_extension_ts="/xdebug.so". Dies fügt die gerade kompilierte Extension hinzu. Wichtig ist hier zum einen die Verwendung von zend_extension oder zend_extension_ts, und nicht einfach extension und die Angabe des absoluten Pfades. Zu beachten ist hierbei noch die Inkompatibilität zum Zend Optimizer und anderen Zend-Erweiterungen. Das heißt: Entweder Xdebug oder Zend. Mit dem Kommando php -m | grep -i xdebug kann man danach prüfen, ob Xdebug geladen wird.

Konfiguration

Im nächsten Schritt wird das Xdebug-Modul in der php.ini konfiguriert. Man soll das Profiling über einen GET-Parameter einschalten können und die Ausgabe soll für die Weiterverarbeitung im Grind-Format in einem lokalen Verzeichnis abgelegt werden, sodass man mit einem lokalen Tool wie WinCacheGrind, KCacheGrind, MacCallGrind oder einem Web-Frontend wie WebCacheGrind auf die Profiling-Daten zugreifen kann. Dazu werden der php.ini folgende Parameter hinzugefügt:

  • xdebug.profiler_enable=Off schaltet das Profiling permanent ein oder aus. Aus ist hier besser, da man das Profiling entweder über die Kommandozeile direkt einschalten oder den URL-GET-Parameter ?XDEBUG_PROFILE verwenden kann.
  • xdebug.profiler_output_dir="/tmp" gibt das Verzeichnis (auf dem Server) an, in dem die Logs gespeichert werden sollen.
  • xdebug.profiler_append=Off bedeutet Xdebug, das Profiling-Log neu zu schreiben und nicht zu erweitern.
  • xdebug.profiler_enable_trigger=On ermöglicht das Einschalten des Profilers für einen bestimmten URL über die Nutzung des GET-Parameters XDEBUG_PROFILE.
  • xdebug.profiler_output_name=cachegrind.out.%R%u: cachegrind.out.* ist die Dateiendung, die z. B. WinCacheGrind erwartet; %R benennt das Profile-Log nach dem verwendeten URI und %u hängt zusätzlich einen Zeitstempel an.

Teil 1   Teil 2   Teil 3   

Kommentare

Gravatar Benjamin Carl 10.12.2010
um 15:34 Uhr
Hallo zusammen!

Ein sehr sehr interessanter Artikel. Ich habe vor längerer Zeit schon versucht für mich selbst herauszufinden mit welchem Werkzeug ich die für mich aussagekräftigsten Ergebnisse erzielen kann. Dies erwies sich also gar nicht so einfach.

Euer Artikel (den ich übrigens im Magazin schon gelesen habe) gibt einen guten Überblick über die Vor- und Nachteile der jeweiligen Lösung.

Selbst bei der Verwendung der Auswertungswerkzeuge gibt es eintscheidene Vor- und Nachteile. Geht es um einen visuellen Überblick auf die schnelle ist kCacheGrind sehr gut geeignet. Möchte ich (insbes.) die Ausführungszeiten auf die schnelle analysieren bevorzuge ich pers. WinCacheGrind (btw: KCachegrind lässt sich übrigens auch super unter Windows mit KDE verwenden).

Neugierig gemacht habt ihr mich dann mit XHProf und der Möglichkeit des A/B-Vergleichs und der Langzeitanalyse!

Leider gab es, wie Facebook auch selber auf der Seite von XHProf verkündet, keine Windows-Version. Die letzte Version 0.9.2 läßt sich lediglich auf Linux und Mac OS kompilieren.
Ich sitze aber bevorzugt (wenn auch anscheinend als einer der letzten :) an meinem Windows (XP x64) Arbeitsplatz.

Deshalb habe ich in den letzten Tagen viel Zeit abgezwackt, meine arg eingerosteten C/C++ Skills wieder zum Leben erweckt und XHProf in Version 0.10.0 veröffentlicht. Bei der Gelegenheit habe ich
den Code leicht gesäubert, unreferenzierte Variablen entfernt und Warning-produzierende Stellen korrigiert. Durch die Einführung der Windows-Unterstützung habe ich mir erlaubt die Version von 0.9.2 auf 0.10.0 zu heben. Eine kompilierte Preview dieser Version erhaltet ihr zum download auf meiner Seite unter http://www.benjamin-carl.de

Den Quelltext veröffentliche ich (sofern nichts dazwischen kommt) noch im Laufe des Tages unter https://github.com/clickalicious/xhprof

Euer Benjamin Carl
#zitieren