[DE] Profiling und Performance-Testing von PHP-Anwendungen

Filed under: Web-Development — Rene @ 16. December 2008 14:00 | Comments (0)

Screenshot KCachegrind Main Window Besonders bei umfangreichen PHP – Applikationen ist es enorm wichtig, schon während der Entwicklung die Performance der Software im Hinterkopf zu behalten. Doch auch für kleinere Anwendungen kann es ganz interessant sein, wo am meisten Scriptlaufzeit verschenkt wird. Das Apache – Modul Xdebug in Kombination mit KCacheGrind ermöglichen eine effektive Analyse von Web-Anwendungen auf Basis von PHP.

Installation von Xdebug

Zuerst installieren wir php5-dev, das für die Installation des Apache-Moduls benötigt wird:

  1. sudo apt-get install php5-dev

Anschließend können wir Xdebug installieren: (Für die meisten Linux – Distributionen steht hält die Paketverwaltung ein entsprechendes Paket bereit)

  1. sudo apt-get install php5-xdebug

Dann fehlt eigentlich nur noch der Eintrag in der php.ini um Xdebug zu aktivieren:

extension=xdebug.so (Pfad zur Xdebug – Installation)
xdebug.profiler_enable = 1
xdebug.profiler_output_dir = /tmp/xdebug

In produktiven Umgebungen ist es auch möglich, Xdebug über die URL anzusteuern:
http://www.meine-domain.de/index.php?XDEBUG_PROFILE=1

Nicht vergessen den Webserver neuzustarten ;-)

Installation von KCacheGrind

Hier stehen für die meisten Linux – Distributionen ebenfalls fertige Pakete bereit:

  1. sudo apt-get install kcachegrind

So, den ersten Teil hätten wir. Jetzt können wir mit der eigentlichen Analyse unserer Web-Apps beginnen.

Auswertung

In der zuvor bearbeiteten Datei php.ini haben wir mit der Direktive xdebug.profiler_output_dir angegeben, wo Xdebug seine Dateien ablegen soll. Bei jedem Skriptaufruf wird hier eine neue Datei angelegt:

  1. cd /tmp/xdebug
  2. ls -la
  3. -rw-r–r– 1 www-data www-data 538731 Oct  1 10:43 cachegrind.out.20404
  4. -rw-r–r– 1 www-data www-data 538731 Oct  1 10:43 cachegrind.out.12245
  5. -rw-r–r– 1 www-data www-data 538731 Oct  1 10:43 cachegrind.out.32987
  6. -rw-r–r– 1 www-data www-data 538731 Oct  1 10:43 cachegrind.out.26792
  7. -rw-r–r– 1 www-data www-data 538731 Oct  1 10:43 cachegrind.out.17952

Folgendes PHP – Skript habe ich zur Veranschaulichung der Funktionnen von KCacheGrind verwendet:

  1. <?php
  2.  
  3. function sleep1() {
  4.     sleep(1);
  5. }
  6.  
  7. function sleep2() {
  8.     sleep(2);
  9. }
  10.  
  11. function sleep4() {
  12.     sleep(4);
  13. }
  14.  
  15. function sleep8() {
  16.     sleep(8);
  17. }
  18.  
  19. sleep1();   // Sleep 1 second
  20. sleep2();   // Sleep 2 seconds
  21. sleep4();   // Sleep 4 seconds
  22. sleep8();   // Sleep 8 second
  23.  
  24. ?>
KCacheGrind - Hauptfenster

KCacheGrind - Hauptfenster

Auf der linken Seite sieht mann alle aufgerufenen Funktionen aufgelistet. Noch kurz zur Erklärung der Spalten:

  • Incl
    Zeit die von der Funktion inkl. aller enhaltenen Code-Teile und derer Funktionen, die diese Funktion aufrufen benötigt wurde
  • Self
    jene Zeit, die von der Funktion selbst (nicht darin aufgerufene Funktionen) benötigt wurde
  • Called
    Anzahl der Funktionsaufrufe
  • Location
    Ort, an dem die Funktion deklariert wurde (Codedatei, php-interne Funktion)

Auf der Callee Map wird nun visuell veranschaulicht, welche Funktionen die meiste Zeit verbraten. (Fläche == Zeit)
Auch sehr interessant ist meiner Meinung nach die Ansicht “Source”, in der man im Quellcode des Scripts sieht, welche Funktionsaufrufe am meisten Zeit brauchen:

KCacheGrind - Source

KCacheGrind - Source

Komplexere Beispiele

Bei größeren Skripten sieht das natürlich wieder ganz anders aus ;) Hier die Callee – Map der Startseite von com to date:

Callee Map - com to date

Callee Map - com to date

Und auf was muss ich jetzt schauen, wenn ich die Performance meiner Anwendungen verbessern will?

  • Call counts

    Wird eine Funktion während eines Skriptdurchlaufs auffällig oft durchlaufen, lohnt es sich meist, diese mal genauer anzusehen. Ich konnte beispielsweise die Skriptlaufzeit von com to date mit dem Entfernen von nur einer Zeile (Hinweis: is_file() ist extrem langsam) um 10% verkürzen.
  • Hohe self-times
    Geht in einer bestimmten Funktion auffallend viel Zeit verloren, kann dort meist noch mit einem Code – Review etwas Performance rausgekitzelt werden.
Tags: , , , ,

No Comments »

No comments yet.

Leave a comment