Domanda

Qual è il modo più semplice per profilare uno script PHP?

Mi piacerebbe aggiungere qualcosa che mi mostri un dump di tutte le chiamate di funzione e quanto tempo hanno impiegato, ma sono anche d'accordo nel mettere qualcosa attorno a funzioni specifiche.

Ho provato a sperimentare con il microtempo funzione:

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

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

ma questo a volte mi dà risultati negativi.Inoltre è un sacco di problemi spargerlo su tutto il mio codice.

È stato utile?

Soluzione

IL PECL APD l'estensione viene utilizzata come segue:

<?php
apd_set_pprof_trace();

//rest of the script
?>

Successivamente, analizza il file generato utilizzando pprofp.

Esempio di output:

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

Avvertimento:l'ultima versione di APD è datata 2004, l'estensione non è più mantenuto e presenta vari problemi di compatibilità (vedi commenti).

Altri suggerimenti

Tu vuoi xdebug Penso.Installalo sul server, accendilo, pompa l'output kcachegrind (per Linux) o wincachegrind (per Windows) e ti mostrerà alcuni graziosi grafici che descrivono in dettaglio i tempi esatti, i conteggi e l'utilizzo della memoria (ma per questo avrai bisogno di un'altra estensione).

È fantastico, sul serio :D

Non sono necessarie estensioni, basta utilizzare queste due funzioni per una semplice profilazione.

// 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>";
}

Ecco un esempio, chiamando prof_flag() con una descrizione ad ogni punto di controllo e prof_print() alla fine:

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

L'output è simile al seguente:

Inizio
   0.004303
Connettiti al DB
   0.003518
Esegui interrogazione
   0.000308
Recuperare i dati
   0.000009
Chiudi DB
   0.000049
Fatto

Pubblicazione incrociata del mio riferimento dalla versione beta di SO Documentation che sta andando offline.

Profilazione con XDebug

È disponibile un'estensione per PHP chiamata Xdebug per assistere profilazione delle applicazioni PHP, nonché il debug in fase di esecuzione.Quando si esegue il profiler, l'output viene scritto in un file in formato binario chiamato "cachegrind".Su ciascuna piattaforma sono disponibili applicazioni per analizzare questi file. Per eseguire questa profilazione non sono necessarie modifiche al codice dell'applicazione.

Per abilitare la profilazione, installa l'estensione e modifica le impostazioni di php.ini.Alcune distribuzioni Linux vengono fornite con pacchetti standard (ad es.Quello di Ubuntu php-xdebug pacchetto).Nel nostro esempio eseguiremo il profilo facoltativamente in base a un parametro di richiesta.Ciò ci consente di mantenere le impostazioni statiche e di attivare il profiler solo se necessario.

# 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"

Successivamente utilizza un client Web per effettuare una richiesta all'URL della tua applicazione che desideri profilare, ad es.

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

Mentre la pagina viene elaborata, scriverà in un file con un nome simile a

/tmp/cachegrind.out.12345

Per impostazione predefinita, il numero nel nome del file è l'ID del processo che lo ha scritto.Questo è configurabile con xdebug.profiler_output_name collocamento.

Tieni presente che scriverà un file per ogni richiesta/processo PHP eseguito.Quindi, ad esempio, se desideri analizzare un post del modulo, verrà scritto un profilo per la richiesta GET per visualizzare il modulo HTML.Il parametro XDEBUG_PROFILE dovrà essere passato alla successiva richiesta POST per analizzare la seconda richiesta che elabora il modulo.Pertanto durante la profilazione a volte è più semplice eseguire curl per POSTARE direttamente un modulo.

Analisi dell'output

Una volta scritta, la cache del profilo può essere letta da un'applicazione come KCachegrind O Webgrind.Anche PHPStorm, un popolare IDE PHP, può visualizzare questi dati di profilazione.

KCachegrind

KCachegrind, ad esempio, mostrerà informazioni tra cui:

  • Funzioni eseguite
  • Tempo di chiamata, sia in sé che comprensivo delle successive chiamate di funzione
  • Numero di volte in cui viene chiamata ciascuna funzione
  • Grafici delle chiamate
  • Collegamenti al codice sorgente

Cosa cercare

Ovviamente l'ottimizzazione delle prestazioni è molto specifica per i casi d'uso di ciascuna applicazione.In generale è bene cercare:

  • Chiamate ripetute alla stessa funzione che non ti aspetteresti di vedere.Per le funzioni che elaborano ed eseguono query sui dati, queste potrebbero essere le principali opportunità di memorizzazione nella cache della tua applicazione.
  • Funzioni lente.Dove trascorre la maggior parte del tempo l'applicazione?il miglior risultato nell'ottimizzazione delle prestazioni è concentrarsi su quelle parti dell'applicazione che consumano più tempo.

Nota:Xdebug, e in particolare le sue funzionalità di profilazione, richiedono molte risorse e rallentano l'esecuzione di PHP.Si consiglia di non eseguirli in un ambiente server di produzione.

Se la sottrazione dei microtempi fornisce risultati negativi, prova a utilizzare la funzione con l'argomento true (microtime(true)).Con true, la funzione restituisce un float invece di una stringa (come avviene se viene chiamata senza argomenti).

Onestamente, sosterrò che usare NewRelic per la profilazione è la soluzione migliore.

È un'estensione PHP che non sembra rallentare affatto il runtime e fanno il monitoraggio per te, consentendo un drill-down decente.Nella versione costosa consentono un drill down pesante (ma non possiamo permetterci il loro modello di prezzo).

Tuttavia, anche con il piano gratuito/standard, è ovvio e semplice dove si trova la maggior parte dei frutti a portata di mano.Mi piace anche che possa darti un'idea anche sulle interazioni DB.

screenshot of one of the interfaces when profiling

PECLXHPROF sembra anche interessante.Esso ha interfaccia HTML cliccabile per visualizzare i report ed è piuttosto semplice documentazione.Devo ancora testarlo però.

Profilazione dei poveri, nessuna estensione richiesta.Supporta profili nidificati e percentuale del totale:

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;
}

Esempio:

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

Rendimenti:

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

Mi piace usare phpDebug per la profilazione.http://phpdebug.sourceforge.net/www/index.html

Fornisce l'intero utilizzo del tempo/della memoria per qualsiasi SQL utilizzato, nonché tutti i file inclusi.Ovviamente, funziona meglio su codice astratto.

Per la profilazione di funzioni e classi userò semplicemente microtime() + get_memory_usage() + get_peak_memory_usage().

Lo darei con aria di sfida Fuoco nero un tentativo.

C'è questo virtualBox che ho messo insieme usando burattino, per testare diversi framework php forniti con BlackFire, sentiti libero di eseguire il fork e/o distribuire se necessario :)

https://github.com/webit4me/PHPFrameworks

Per il benchmarking, come nel tuo esempio, utilizzo il file Benchmark pera pacchetto.Imposta i marcatori per la misurazione.Il corso fornisce anche alcuni aiutanti per la presentazione oppure puoi elaborare i dati come ritieni opportuno.

In realtà l'ho racchiuso in un'altra classe con un metodo __destruct.Quando uno script esce, l'output viene registrato tramite log4php su syslog, quindi ho molti dati sulle prestazioni su cui lavorare.

XDebug non è stabile e non è sempre disponibile per una particolare versione di php.Ad esempio, su alcuni server eseguo ancora php-5.1.6, - è ciò che viene fornito con RedHat RHEL5 (e tra l'altro riceve ancora aggiornamenti per tutte le questioni importanti), e il recente XDebug non viene nemmeno compilato con questo php.Quindi ho finito per passare a Debug DBGSuo benchmarking di php fornisce tempistiche per funzioni, metodi, moduli e persino linee.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top