Einfachste Möglichkeit, ein PHP-Skript zu profilieren

289

Was ist der einfachste Weg, ein PHP-Skript zu profilieren?

Ich würde gerne etwas anheften, das mir einen Speicherauszug aller Funktionsaufrufe zeigt und wie lange sie gedauert haben, aber ich bin auch damit einverstanden, etwas um bestimmte Funktionen herum zu platzieren.

Ich habe versucht, mit der Mikrozeitfunktion zu experimentieren :

$then = microtime();
myFunc();
$now = microtime();

echo sprintf("Elapsed:  %f", $now-$then);

aber das gibt mir manchmal negative ergebnisse. Außerdem ist es eine Menge Mühe, das über meinen Code zu streuen.

Mark Biek
quelle
7
Hey Mark, schau
Mina
16
Dieser von @Midiane verlinkte Kommentar macht keinen Sinn. Wenn es das Problem des Kommentators zu lösen schien, muss es ein Zufall gewesen sein. Nur die Verwendung microtime()führt dazu, dass manchmal Ausdrücke wie: "0.00154800 1342892546" - "0.99905700 1342892545"ausgewertet werden, die wie: ausgewertet werden 0.001548 - 0.999057. Sie können verwendet werden microtime( TRUE ), wie es um dieses Problem zu vermeiden , weist darauf hin , durch @luka.
JMM

Antworten:

104

Die PECL APD- Erweiterung wird wie folgt verwendet:

<?php
apd_set_pprof_trace();

//rest of the script
?>

Analysieren Sie anschließend die generierte Datei mit pprofp.

Beispielausgabe:

Trace for /home/dan/testapd.php
Total Elapsed Time = 0.00
Total System Time  = 0.00
Total User Time    = 0.00


Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
100.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0009            0 main
56.9 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0005   0.0005            0 apd_set_pprof_trace
28.0 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 preg_replace
14.3 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 str_replace

Warnung: Die neueste Version von APD ist auf das Jahr 2004 datiert, die Erweiterung wird nicht mehr beibehalten und weist verschiedene Kompatibilitätsprobleme auf (siehe Kommentare).

Vincent
quelle
19
Die APD-Erweiterung ist auf PHP 5.4 defekt.
Skynet
Als Antwort auf user457015 konnte ich es auf einer Website mit WordPress 3.8.1 und PHP 5.3.10 zum Laufen bringen, und es schien einwandfrei zu funktionieren.
Supernovah
1
@Supernovah, Benutzer457015 hat PHP 5.4 gesagt. Er sagte nicht, dass es auf PHP 5.3 kaputt war.
Magnus
@ user1420752 Ich verwende 5.3.27 und es läuft dort auch nicht. Ich erhalte einen undefinierten Funktionsfehler.
Fractaly
2
Die neueste Version von APD stammt aus dem Jahr 2004 (!). Es funktioniert nicht mit PHP 7. Wenn Sie versuchen, für PHP 5 mit zu installieren pecl install apd, wird eine Fehlermeldung zu "config.m4" angezeigt. Es scheint, als müssten Sie es von der Quelle installieren, was ich noch nicht ausprobiert habe. Im Ernst, gibt es nicht ein modernes, aktualisiertes CLI-basiertes Profiling-Tool für PHP, das mit Homebrew installiert wird, nur minimale Einstellungen erfordert und eine leicht lesbare Ausgabe liefert?
Forthrin
267

Du willst xdebug, denke ich. Installieren Sie es auf dem Server, schalten Sie es ein, pumpen Sie die Ausgabe über kcachegrind (für Linux) oder wincachegrind (für Windows) und es zeigt Ihnen einige hübsche Diagramme, in denen die genauen Zeiten, die Anzahl und die Speichernutzung aufgeführt sind (aber Sie werden es tun) brauche eine andere Erweiterung dafür).

Es rockt ernsthaft: D.

mercutio
quelle
6
Ich fand das viel einfacher zu implementieren als die APD-Lösung. Aber vielleicht liegt das daran, dass APD aus irgendeinem Grund auf meinem System nicht richtig kompiliert wurde. Auch die Charts von kcachegrind waren so hübsch wie versprochen.
wxs
1
@ EvilPuppetMaster, müssen Sie PHP mit --enable-memory-limit kompilieren oder eine modernere PHP-Version verwenden. Siehe xdebug.org/docs/basic#xdebug_memory_usage
mercutio
52
xdebug + webgrind wurde schnell zu meiner bevorzugten Waffe für die schnelle und einfache Profilerstellung. code.google.com/p/webgrind
xkcd150
6
xdebug + xdebug_start_trace () + xdebug_stop_trace () = win
quano
3
Dies war sehr einfach, um mit XAMPP unter Windows zu arbeiten. Netbeans waren bereits für xdebug konfiguriert. Sie müssen lediglich eine xdebug-Einstellung in php.ini in xdebug.profiler_output_name = "cachegrind.out.% T-% s" ändern. Andernfalls wird keine Ausgabe generiert. Erfordert einen Neustart von Apache.
Anfänger_
97

Es sind keine Erweiterungen erforderlich. Verwenden Sie einfach diese beiden Funktionen für die einfache Profilerstellung.

// Call this at each point of interest, passing a descriptive string
function prof_flag($str)
{
    global $prof_timing, $prof_names;
    $prof_timing[] = microtime(true);
    $prof_names[] = $str;
}

// Call this when you're done and want to see the results
function prof_print()
{
    global $prof_timing, $prof_names;
    $size = count($prof_timing);
    for($i=0;$i<$size - 1; $i++)
    {
        echo "<b>{$prof_names[$i]}</b><br>";
        echo sprintf("&nbsp;&nbsp;&nbsp;%f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
    }
    echo "<b>{$prof_names[$size-1]}</b><br>";
}

Hier ist ein Beispiel, in dem prof_flag () mit einer Beschreibung an jedem Prüfpunkt und prof_print () am Ende aufgerufen wird:

prof_flag("Start");

   include '../lib/database.php';
   include '../lib/helper_func.php';

prof_flag("Connect to DB");

   connect_to_db();

prof_flag("Perform query");

   // Get all the data

   $select_query = "SELECT * FROM data_table";
   $result = mysql_query($select_query);

prof_flag("Retrieve data");

   $rows = array();
   $found_data=false;
   while($r = mysql_fetch_assoc($result))
   {
       $found_data=true;
       $rows[] = $r;
   }

prof_flag("Close DB");

   mysql_close();   //close database connection

prof_flag("Done");
prof_print();

Die Ausgabe sieht folgendermaßen aus:

Start
   0.004303
Verbindung zum DB
   0.003518
Perform Abfrage
   0.000308
Abrufen von Daten
   0.000009
Schließen DB
   0.000049
Erledigt

TimH - Codidact
quelle
37

Cross-Posting meiner Referenz aus der SO Documentation Beta, die offline geschaltet wird.

Profilerstellung mit XDebug

Eine PHP-Erweiterung namens Xdebug hilft bei der Profilerstellung von PHP-Anwendungen sowie beim Debuggen zur Laufzeit. Beim Ausführen des Profilers wird die Ausgabe in eine Datei in einem Binärformat namens "Cachegrind" geschrieben. Auf jeder Plattform stehen Anwendungen zur Analyse dieser Dateien zur Verfügung. Für diese Profilerstellung sind keine Änderungen des Anwendungscodes erforderlich.

Um die Profilerstellung zu aktivieren, installieren Sie die Erweiterung und passen Sie die Einstellungen für php.ini an. Einige Linux-Distributionen werden mit Standardpaketen geliefert (z. B. Ubuntus php-xdebugPaket). In unserem Beispiel führen wir das Profil optional basierend auf einem Anforderungsparameter aus. Dies ermöglicht es uns, die Einstellungen statisch zu halten und den Profiler nur bei Bedarf einzuschalten.

# php.ini settings
# Set to 1 to turn it on for every request
xdebug.profiler_enable = 0
# Let's use a GET/POST parameter to turn on the profiler
xdebug.profiler_enable_trigger = 1
# The GET/POST value we will pass; empty for any value
xdebug.profiler_enable_trigger_value = ""
# Output cachegrind files to /tmp so our system cleans them up later
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_output_name = "cachegrind.out.%p"

Verwenden Sie als Nächstes einen Webclient, um eine Anfrage an die URL Ihrer Anwendung zu stellen, die Sie profilieren möchten, z

http://example.com/article/1?XDEBUG_PROFILE=1

Während der Verarbeitung der Seite wird in eine Datei mit einem ähnlichen Namen wie geschrieben

/tmp/cachegrind.out.12345

Standardmäßig ist die Nummer im Dateinamen die Prozess-ID, die sie geschrieben hat. Dies ist mit der xdebug.profiler_output_nameEinstellung konfigurierbar .

Beachten Sie, dass für jede ausgeführte PHP-Anforderung / jeden ausgeführten PHP-Prozess eine Datei geschrieben wird. Wenn Sie beispielsweise einen Formularbeitrag analysieren möchten, wird ein Profil für die GET-Anforderung geschrieben, um das HTML-Formular anzuzeigen. Der Parameter XDEBUG_PROFILE muss an die nachfolgende POST-Anforderung übergeben werden, um die zweite Anforderung zu analysieren, die das Formular verarbeitet. Daher ist es bei der Profilerstellung manchmal einfacher, Curl auszuführen, um ein Formular direkt zu POSTEN.

Analyse der Ausgabe

Nach dem Schreiben kann der Profilcache von einer Anwendung wie KCachegrind oder Webgrind gelesen werden . PHPStorm, eine beliebte PHP-IDE, kann diese Profildaten auch anzeigen .

KCachegrind

KCachegrind zeigt beispielsweise Informationen an, darunter:

  • Funktionen ausgeführt
  • Aufrufzeit, sowohl selbst als auch einschließlich nachfolgender Funktionsaufrufe
  • Häufigkeit, mit der jede Funktion aufgerufen wird
  • Diagramme aufrufen
  • Links zum Quellcode

Wonach schauen

Offensichtlich ist die Leistungsoptimierung sehr spezifisch für die Anwendungsfälle jeder Anwendung. Im Allgemeinen ist es gut zu suchen:

  • Wiederholte Aufrufe derselben Funktion, die Sie nicht erwarten würden. Für Funktionen, die Daten verarbeiten und abfragen, sind dies möglicherweise die besten Möglichkeiten für Ihre Anwendung, zwischengespeichert zu werden.
  • Langsam laufende Funktionen. Wo verbringt die Anwendung die meiste Zeit? Die beste Auszahlung bei der Leistungsoptimierung besteht darin, sich auf die Teile der Anwendung zu konzentrieren, die am meisten Zeit in Anspruch nehmen.

Hinweis : Xdebug und insbesondere seine Profiling-Funktionen sind sehr ressourcenintensiv und verlangsamen die PHP-Ausführung. Es wird empfohlen, diese nicht in einer Produktionsserverumgebung auszuführen.

Matt S.
quelle
3
Hinzufügen zur Liste der Tools zum Parsen des
Profilcaches
1
@ Peter Ich habe vergessen, dass PHPStorm diese Funktion hat. Ich habe es mit einem Link zur Dokumentation hinzugefügt. Vielen Dank!
Matt S
Gibt es eine Möglichkeit, einen Textbericht (ohne GUI) direkt auf dem Server abzurufen?
Alexander Shcheblikin
1
@ Mark könnten Sie dies bitte als Antwort markieren. Die aktuelle Antwort war veraltet, selbst wenn sie veröffentlicht wurde, und hat seit vielen Jahren nicht mehr funktioniert. Das funktioniert, und ich kenne keine bessere Methode.
Mawg sagt, Monica
24

Wenn das Subtrahieren von Mikrotzeiten zu negativen Ergebnissen führt, verwenden Sie die Funktion mit dem Argument true( microtime(true)). Mit truegibt die Funktion ein Float anstelle eines Strings zurück (wie es der Fall ist, wenn es ohne Argumente aufgerufen wird).

luka
quelle
24

Ehrlich gesagt werde ich argumentieren, dass die Verwendung von NewRelic für die Profilerstellung das Beste ist.

Es ist eine PHP-Erweiterung, die die Laufzeit anscheinend überhaupt nicht verlangsamt. Sie übernimmt die Überwachung für Sie und ermöglicht einen angemessenen Drilldown. In der teuren Version erlauben sie schwere Drilldowns (aber wir können uns ihr Preismodell nicht leisten).

Selbst mit dem kostenlosen / Standardplan ist es offensichtlich und einfach, wo sich die meisten niedrig hängenden Früchte befinden. Mir gefällt auch, dass es Ihnen auch eine Vorstellung von DB-Interaktionen geben kann.

Screenshot einer der Schnittstellen bei der Profilerstellung

Zeroasterisk
quelle
16
New Relic sieht vielversprechend aus. Der Teil "Offenlegung Ihrer Anwendungsdaten" in ihrer Datenschutzrichtlinie hat mich jedoch sofort abgestoßen. Imho, es ist etwas zu viel, proprietären Quellcode mit Dritten zu teilen .
Cengiz Can
8
Hier wird nicht zu ihrer Verteidigung gesprungen, aber es sieht so aus, als ob "Anwendungsdaten" nur Leistungsinformationen und Systemkonfigurationsinformationen sind, nicht Ihr Anwendungsquellcode.
David Shields
Mein neues Relikt zeigt meine "WebTransaction" in 99% der Fälle an und hat kein Pro-Konto für "ApplicationTraces"
Karthik T
1
Versuchen Sie, sich anzumelden unter : newrelic.com/rackspace <sollte Ihnen kostenlos "Standard" geben
zeroasterisk
15

Profiling des armen Mannes, keine Erweiterungen erforderlich. Unterstützt verschachtelte Profile und Prozent der Gesamtzahl:

function p_open($flag) {
    global $p_times;
    if (null === $p_times)
        $p_times = [];
    if (! array_key_exists($flag, $p_times))
        $p_times[$flag] = [ 'total' => 0, 'open' => 0 ];
    $p_times[$flag]['open'] = microtime(true);
}

function p_close($flag)
{
    global $p_times;
    if (isset($p_times[$flag]['open'])) {
        $p_times[$flag]['total'] += (microtime(true) - $p_times[$flag]['open']);
        unset($p_times[$flag]['open']);
    }
}

function p_dump()
{
    global $p_times;
    $dump = [];
    $sum  = 0;
    foreach ($p_times as $flag => $info) {
        $dump[$flag]['elapsed'] = $info['total'];
        $sum += $info['total'];
    }
    foreach ($dump as $flag => $info) {
        $dump[$flag]['percent'] = $dump[$flag]['elapsed']/$sum;
    }
    return $dump;
}

Beispiel:

<?php

p_open('foo');
sleep(1);
p_open('bar');
sleep(2);
p_open('baz');
sleep(3);
p_close('baz');
sleep(2);
p_close('bar');
sleep(1);
p_close('foo');

var_dump(p_dump());

Ausbeuten:

array:3 [
  "foo" => array:2 [
    "elapsed" => 9.000766992569
    "percent" => 0.4736904954747
  ]
  "bar" => array:2 [
    "elapsed" => 7.0004580020905
    "percent" => 0.36841864946596
  ]
  "baz" => array:2 [
    "elapsed" => 3.0001420974731
    "percent" => 0.15789085505934
  ]
]
Bischof
quelle
13

PECL XHPROF sieht ebenfalls interessant aus. Es hat eine anklickbare HTML-Oberfläche zum Anzeigen von Berichten und eine ziemlich einfache Dokumentation . Ich muss es allerdings noch testen.

Josef Sábl
quelle
Das sieht so aus, als würde es nicht viel Liebe bekommen. Letzte Aktualisierung im Jahr 2009, keine PEAR-Pakete für 5.3, 5.4 und
höher
1
Facebook erstellte eine Gabel mit Unterstützung durch PHP 5.5 github.com/facebook/xhprof
Borkencode
Überprüfen Sie auch diese Gabel, die einige zusätzliche Anpassungen vorschlägt: github.com/preinheimer/xhprof
Fedir RYKHTIK
xhprof.io bietet eine grafische Benutzeroberfläche für mit XHProf gesammelte Daten sowie die Möglichkeit, Daten für historische Analysezwecke in der Datenbank zu speichern. Ich bin der Autor der letzteren Implementierung.
Gajus
10

Ich benutze gerne phpDebug für die Profilerstellung. http://phpdebug.sourceforge.net/www/index.html

Es gibt die gesamte Zeit- / Speichernutzung für jedes verwendete SQL sowie alle enthaltenen Dateien aus. Offensichtlich funktioniert es am besten mit abstrahiertem Code.

Für die Funktions- und Klassenprofilerstellung verwende ich einfach microtime()+ get_memory_usage()+ get_peak_memory_usage().

Eric Lamb
quelle
6

Für das Benchmarking verwende ich wie in Ihrem Beispiel das Birnen-Benchmark- Paket. Sie setzen Marker zum Messen. Die Klasse bietet auch einige Präsentationshilfen, oder Sie können die Daten nach Belieben verarbeiten.

Ich habe es tatsächlich in einer anderen Klasse mit einer __destruct-Methode verpackt. Wenn ein Skript beendet wird, wird die Ausgabe über log4php in syslog protokolliert, sodass ich viele Leistungsdaten zur Verfügung habe.

Gary Richardson
quelle
3

XDebug ist nicht stabil und für bestimmte PHP-Versionen nicht immer verfügbar. Zum Beispiel führe ich auf einigen Servern immer noch PHP-5.1.6 aus - es ist das, was mit RedHat RHEL5 geliefert wird (und übrigens erhält es immer noch Updates für alle wichtigen Probleme), und der aktuelle XDebug kompiliert nicht einmal mit diesem PHP. Am Ende wechselte ich zum DBG-Debugger. Das PHP-Benchmarking bietet Timing für Funktionen, Methoden, Module und sogar Zeilen.

user2221743
quelle
2

Sie alle sollten auf jeden Fall diesen neuen PHP-Profiler überprüfen.

https://github.com/NoiseByNorthwest/php-spx

Es definiert die Art und Weise neu, wie PHP-Profiler das Ergebnis sammeln und präsentieren. Anstatt nur eine Gesamtzahl bestimmter Funktionsaufrufe und die Gesamtzeit für deren Ausführung auszugeben, präsentiert PHP-SPX die gesamte Zeitleiste der Anforderungsausführung auf perfekt lesbare Weise. Unten sehen Sie den Bildschirm der GUI.

Geben Sie hier die Bildbeschreibung ein

Jacek Dziurdzikowski
quelle