Der einfachste Weg, ein PHP-Skript zu profilieren

Lesezeit: 9 Minuten

Der einfachste Weg ein PHP Skript zu profilieren
Markus Biek

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

Ich würde gerne etwas anheften, das mir einen Dump 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 dem zu experimentieren Mikrozeit Funktion:

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

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

aber das gibt mir manchmal negative Ergebnisse. Außerdem ist es eine Menge Ärger, das über meinen gesamten Code zu streuen.

  • Hey Mark, schau dir diesen Kommentar an, um dir zu helfen, die negativen Kommentare zu lösen: ro.php.net/manual/en/function.microtime.php#99524

    – Mina

    8. März 2012 um 10:59 Uhr

  • Dieser von @Midiane verlinkte Kommentar ergibt keinen Sinn. Wenn es das Problem des Kommentators zu lösen schien, muss es ein Zufall gewesen sein. Nur mit microtime() führt dazu, dass manchmal Ausdrücke ausgewertet werden wie: "0.00154800 1342892546" - "0.99905700 1342892545"die wie folgt bewertet wird: 0.001548 - 0.999057. Sie können verwenden microtime( TRUE ) um dieses Problem zu vermeiden, wie von @luka hervorgehoben.

    – JMM

    21. Juli 2012 um 18:16 Uhr

1646914449 594 Der einfachste Weg ein PHP Skript zu profilieren
Merkur

Sie wollen xdebug Ich denke. Installieren Sie es auf dem Server, schalten Sie es ein, pumpen Sie die Ausgabe durch Cachegrind (für Linux) bzw wincachegrind (für Windows) und es zeigt Ihnen ein paar hübsche Diagramme, die die genauen Timings, Zählungen und die Speichernutzung anzeigen (aber dafür benötigen Sie eine andere Erweiterung).

Es rockt, ernsthaft 😀

  • Ich fand dies 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

    5. Dezember 2008 um 16:23 Uhr

  • xdebug + webgrind wurde schnell zu meiner bevorzugten Waffe für schnelles und einfaches Profiling. code.google.com/p/webgrind

    – xkcd150

    27. April 2010 um 11:32 Uhr

  • xdebug + xdebug_start_trace() + xdebug_stop_trace() = gewinnen

    – Quano

    9. Mai 2011 um 11:24 Uhr


  • Dies war sehr einfach unter Windows mit XAMPP zum Laufen zu bringen. Hatte Netbeans bereits für xdebug konfiguriert. Das Einzige, was Sie tun müssen, ist eine xdebug-Einstellung in php.ini auf xdebug.profiler_output_name = “cachegrind.out.%t-%s” zu ändern, sonst wird keine Ausgabe generiert. Erfordert einen Neustart von Apache.

    – Anfänger_

    27. September 2012 um 11:45 Uhr

  • Dies sollte die beste/akzeptierte Antwort sein. Ich habe eine halbe Stunde gebraucht, um alles zum Laufen zu bringen (mit dem Kompilieren von xdebug aus der Quelle). Solide Beratung.

    – Mike Starow

    17. Juli 2014 um 20:13 Uhr

Der einfachste Weg ein PHP Skript zu profilieren
TimH – Codidakt

Es werden keine Erweiterungen benötigt, verwenden Sie einfach diese beiden Funktionen für einfaches Profiling.

// 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, das prof_flag() mit einer Beschreibung an jedem Checkpoint und prof_print() am Ende aufruft:

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();

Ausgabe sieht so aus:

Start
0,004303
Verbinden Sie sich mit DB
0,003518
Abfrage durchführen
0,000308
Daten abrufen
0,000009
DB schließen
0,000049
Getan

1646914450 384 Der einfachste Weg ein PHP Skript zu profilieren
Vinzenz

Die PECL-APD Erweiterung wird wie folgt verwendet:

<?php
apd_set_pprof_trace();

//rest of the script
?>

Analysieren Sie danach 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

Achtung: Die neueste Version von APD ist von 2004, die Erweiterung wird nicht mehr gepflegt und hat verschiedene Kompatibilitätsprobleme (siehe Kommentare).

  • Die APD-Erweiterung ist auf PHP 5.4 defekt.

    – SkyNet

    24. Januar 2013 um 20:59 Uhr

  • 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 gut zu funktionieren.

    – Supernova

    2. März 2014 um 13:48 Uhr

  • @Supernovah, user457015 hat PHP 5.4 gesagt. Er hat nicht gesagt, dass es unter PHP 5.3 kaputt war.

    – magnus

    22. Oktober 2015 um 23:24 Uhr

  • @ user1420752 Ich verwende 5.3.27 und es läuft dort auch nicht. Ich erhalte einen undefinierten Funktionsfehler.

    – Fraktal

    13. August 2016 um 18:24 Uhr

  • Die neueste Version von APD ist von 2004 (!) Es funktioniert nicht mit PHP 7. Wenn Sie versuchen, PHP 5 mit zu installieren pecl install apd, es gibt eine Fehlermeldung über “config.m4”. Es scheint, als müssten Sie es von der Quelle installieren, was ich noch nicht versucht habe. Im Ernst, gibt es kein modernes, aktualisiertes CLI-basiertes Profilerstellungstool für PHP, das mit Homebrew installiert wird, minimale Einrichtung erfordert und eine leicht lesbare Ausgabe liefert?

    – forrin

    29. August 2016 um 6:38 Uhr

1646914451 477 Der einfachste Weg ein PHP Skript zu profilieren
Matt S

Cross-Posting meiner Referenz von SO Documentation Beta, die offline geht.

Profilerstellung mit XDebug

Zur Unterstützung steht eine Erweiterung für PHP namens Xdebug zur Verfügung Profilerstellung von PHP-Anwendungen, sowie Laufzeit-Debugging. Beim Ausführen des Profilers wird die Ausgabe in eine Datei in einem binären Format namens “cachegrind” geschrieben. Anwendungen sind auf jeder Plattform verfügbar, um diese Dateien zu analysieren. Für diese Profilerstellung sind keine Änderungen am Anwendungscode erforderlich.

Um die Profilerstellung zu aktivieren, installieren Sie die Erweiterung und passen Sie die php.ini-Einstellungen an. Einige Linux-Distributionen enthalten Standardpakete (z. B. Ubuntus php-xdebug Paket). In unserem Beispiel führen wir das Profil optional basierend auf einem Anforderungsparameter aus. Dadurch können wir die Einstellungen statisch halten und den Profiler nur bei Bedarf aktivieren.

# 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 die Seite verarbeitet wird, schreibt sie in eine Datei mit einem ähnlichen Namen wie

/tmp/cachegrind.out.12345

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

Beachten Sie, dass für jede ausgeführte PHP-Anforderung / jeden ausgeführten PHP-Prozess eine Datei geschrieben wird. Wenn Sie also beispielsweise einen Formularbeitrag analysieren möchten, wird ein Profil für die GET-Anfrage 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 beim Profiling manchmal einfacher, curl auszuführen, um ein Formular direkt zu POST.

Analysieren der Ausgabe

Nach dem Schreiben kann der Profilcache von einer Anwendung wie z. B. gelesen werden KCachegrind oder Webgrind. PHPStorm, eine beliebte PHP-IDE, kann das auch diese Profiling-Daten anzuzeigen.

KCachegrind

KCachegrind zeigt beispielsweise folgende Informationen an:

  • Funktionen ausgeführt
  • Aufrufzeit, sowohl selbst als auch einschließlich nachfolgender Funktionsaufrufe
  • Anzahl der Aufrufe jeder Funktion
  • Graphen 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, könnten dies hervorragende Gelegenheiten für Ihre Anwendung zum Zwischenspeichern sein.
  • 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 die meiste Zeit in Anspruch nehmen.

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

1646914451 116 Der einfachste Weg ein PHP Skript zu profilieren
Lukas

Wenn das Subtrahieren von Microtimes negative Ergebnisse liefert, versuchen Sie, die Funktion mit dem Argument zu verwenden true (microtime(true)). Mit truegibt die Funktion einen Float anstelle einer Zeichenfolge zurück (wie es der Fall ist, wenn sie ohne Argumente aufgerufen wird).

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

Es ist eine PHP-Erweiterung, die die Laufzeit überhaupt nicht zu verlangsamen scheint, und sie übernimmt die Überwachung für Sie, was einen anständigen Drilldown ermöglicht. In der teuren Version erlauben sie einen starken Drilldown (aber wir können uns ihr Preismodell nicht leisten).

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

Screenshot einer der Schnittstellen beim Profiling

1646914452 232 Der einfachste Weg ein PHP Skript zu profilieren
Bischof

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

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());

Erträge:

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
  ]
]

987870cookie-checkDer einfachste Weg, ein PHP-Skript zu profilieren

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy