Il modo più semplice per profilare uno script PHP


289

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

Mi piacerebbe affrontare qualcosa che mi mostra una discarica di tutte le chiamate di funzione e quanto tempo hanno impiegato, ma sto anche bene nel mettere qualcosa intorno a funzioni specifiche.

Ho provato a sperimentare la funzione microtime :

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

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

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


7
hey Mark, dai un'occhiata a questo commento per aiutarti a risolvere i commenti negativi: ro.php.net/manual/en/function.microtime.php#99524
Mina

16
Quel commento collegato da @Midiane non ha senso. Se sembrava risolvere il problema del commentatore, doveva essere stata una coincidenza. Usando solo microtime()porterà ad espressioni a volte valutando come: "0.00154800 1342892546" - "0.99905700 1342892545"che valuterà come: 0.001548 - 0.999057. Puoi usarlo microtime( TRUE )per evitare quel problema, come sottolineato da @luka.
JMM,

Risposte:


104

L' estensione APD PECL viene utilizzata come segue:

<?php
apd_set_pprof_trace();

//rest of the script
?>

Successivamente, analizzare 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

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


19
L'estensione APD è rotta su php 5.4.
Skynet,

In risposta a user457015, sono stato in grado di farlo funzionare su un sito Web con Wordpress 3.8.1 e PHP 5.3.10 e sembrava funzionare bene.
Supernovah

1
@Supernovah, user457015 ha detto PHP 5.4. Non ha detto che era rotto su PHP 5.3.
magnus,

@ user1420752 Sto eseguendo 5.3.27 e non funziona anche lì. Ottengo un errore di funzione indefinito.
Frattaly,

2
L'ultima versione di APD risale al 2004 (!) Non funziona con PHP 7. Quando si tenta di installare per PHP 5 con pecl install apd, viene visualizzato un messaggio di errore su "config.m4". Sembra che tu debba installarlo dalla fonte, cosa che non ho ancora provato. Scherzi a parte, non esiste uno strumento di profilazione moderno e aggiornato basato sulla CLI per PHP che si installa con Homebrew, richiede una configurazione minima e fornisce un output facilmente leggibile dall'uomo?
Outrin

267

Vuoi xdebug, penso. Installalo sul server, accendilo , pompa l'output tramite kcachegrind (per Linux) o Wincachegrind (per Windows) e ti mostrerà alcuni graziosi grafici che dettagliano i tempi esatti, i conteggi e l'uso della memoria (ma serve un'altra estensione per quello).

Oscilla, sul serio: D


6
L'ho trovato molto più facile da implementare rispetto alla soluzione APD. Ma forse è perché per qualche motivo APD non è stato compilato correttamente sul mio sistema. Anche i grafici di kcachegrind erano belli come promesso.
wxs,

1
@EvilPuppetMaster, devi compilare php con --enable-memory-limit o utilizzare una versione php più moderna. Vedi xdebug.org/docs/basic#xdebug_memory_usage
mercutio

52
xdebug + webgrind è diventata rapidamente la mia arma preferita per una profilazione semplice e veloce. code.google.com/p/webgrind
xkcd150

6
xdebug + xdebug_start_trace () + xdebug_stop_trace () = win
quano

3
È stato molto facile lavorare su Windows con XAMPP. Già netbeans era configurato per xdebug. L'unica cosa che devi fare è cambiare un'impostazione di xdebug in php.ini in xdebug.profiler_output_name = "cachegrind.out.% T-% s", altrimenti non verrà generato alcun output. Richiede il riavvio di apache.
principiante_

97

Non sono necessarie estensioni, basta usare 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 per ciascun checkpoint 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:

Avvia
   0,004303
Connetti a DB
   0,003518
Esegui query
   0,000308
Recupera dati
   0,000009
Chiudi DB
   0,000049
Fine


37

Pubblicazione incrociata del mio riferimento dalla documentazione beta SO che non è in linea.

Profilazione con XDebug

Un'estensione di PHP chiamata Xdebug è disponibile per assistere nella creazione di profili di applicazioni PHP , nonché nel debug di runtime. Quando si esegue il profiler, l'output viene scritto in un file in un formato binario chiamato "cachegrind". Le applicazioni sono disponibili su ciascuna piattaforma per analizzare questi file. Non sono necessarie modifiche al codice dell'applicazione per eseguire questa profilazione.

Per abilitare il profiling, installa l'estensione e regola le impostazioni di php.ini. Alcune distribuzioni Linux vengono fornite con pacchetti standard (ad esempio il php-xdebugpacchetto Ubuntu ). Nel nostro esempio eseguiremo il profilo facoltativamente in base a un parametro di richiesta. Questo ci consente di mantenere le impostazioni statiche e 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"

Quindi utilizzare un client Web per effettuare una richiesta all'URL dell'applicazione che si desidera profilare, ad es

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

Man mano che la pagina viene elaborata, verrà scritta in un file con un nome simile a

/tmp/cachegrind.out.12345

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

Nota che scriverà un file per ogni richiesta / processo PHP che viene eseguito. Ad esempio, se si desidera analizzare un post di un 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, quando si profila, a volte è più semplice eseguire curl per inviare direttamente un modulo.

Analizzare l'uscita

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

KCachegrind

KCachegrind, ad esempio, mostrerà informazioni tra cui:

  • Funzioni eseguite
  • Tempo di chiamata, sia esso stesso che comprensivo delle successive chiamate di funzione
  • Numero di volte in cui viene chiamata ciascuna funzione
  • Grafici di chiamata
  • 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 per la stessa funzione che non ti aspetteresti di vedere. Per le funzioni che elaborano e interrogano i dati, queste potrebbero essere le principali opportunità per la cache dell'applicazione.
  • Funzioni a funzionamento lento. 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.


3
Aggiunta all'elenco di strumenti per l'analisi della cache del profilo: PhpStorm ha anche uno strumento per l'anteprima della cache del profilo
peterchaula,

1
@peter Ho dimenticato che PHPStorm ha questa funzione. L'ho aggiunto con un collegamento alla documentazione. Grazie!
Matt S

Un modo per ottenere un rapporto di testo (non GUI) direttamente sul server?
Alexander Shcheblikin,

1
@Mark potresti contrassegnarlo come risposta, per favore. La risposta attuale era obsoleta anche se pubblicata e non ha funzionato per molti anni. Questo funziona e non conosco alcun metodo migliore.
Mawg dice di ripristinare Monica il

24

Se la sottrazione dei microtimi ti dà risultati negativi, prova a utilizzare la funzione con l'argomento true(microtime(true) ). Con true, la funzione restituisce un float anziché una stringa (come succede se viene chiamata senza argomenti).


24

Onestamente, ho intenzione di sostenere che l'utilizzo di NewRelic per la profilazione è il 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 approfondimento approfondito (ma non possiamo permetterci il loro modello di prezzi).

Tuttavia, anche con il piano gratuito / standard, è ovvio e semplice dove si trova la maggior parte della frutta bassa. Mi piace anche che possa darti un'idea anche sulle interazioni tra DB.

screenshot di una delle interfacce durante la creazione del profilo


16
New Relic sembra promettente, certo. Tuttavia, "Divulgazione dei dati delle tue applicazioni" parte della loro Informativa sulla privacy mi ha respinto immediatamente. Imho, condividere parti di codice sorgente proprietario con terze parti è un po 'troppo.
Cengiz Can

8
Non saltando a loro difesa qui, ma sembra che "Dati applicazioni" siano solo informazioni sulle prestazioni e informazioni sulla configurazione del sistema, non il codice sorgente dell'applicazione.
David Shields,

La mia nuova reliquia sta mostrando la mia "WebTransaction" come il 99% delle volte e non ho l'account pro per "ApplicationTraces"
Karthik T

1
prova a registrarti su: newrelic.com/rackspace <dovrebbe darti "standard" gratis
zeroasterisk

15

Profilazione del povero uomo, 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());

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

13

Anche PECL XHPROF sembra interessante. Ha un'interfaccia HTML cliccabile per visualizzare i report e una documentazione piuttosto semplice . Devo ancora provarlo però.


Sembra che non stia ottenendo molto amore. Ultimo aggiornamento nel 2009, nessun pacchetto PEAR per 5.3, 5.4 e oltre ...
dland

1
Facebook ha creato un fork con supporto tramite php 5.5 github.com/facebook/xhprof
codice bork

Controlla anche questa forcella che propone alcuni aggiustamenti aggiuntivi: github.com/preinheimer/xhprof
Fedir RYKHTIK

xhprof.io fornisce la GUI per i dati raccolti usando XHProf, oltre alla possibilità di archiviare i dati nel database per scopi di analisi storica. Sono l'autore di quest'ultima implementazione.
Gajus,

10

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

Emette tutto il tempo / utilizzo della memoria per qualsiasi SQL utilizzato, nonché tutti i file inclusi. Ovviamente, funziona meglio sul codice estratto.

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



6

Per il benchmarking, come nel tuo esempio, uso il pacchetto pera Benchmark . Si impostano i marker per la misurazione. La classe fornisce anche alcuni aiutanti di presentazione, oppure puoi elaborare i dati come ritieni opportuno.

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


3

XDebug non è stabile e non è sempre disponibile per particolari versioni di php. Ad esempio su alcuni server eseguo ancora php-5.1.6, - è quello che viene fornito con RedHat RHEL5 (e tra l'altro riceve ancora aggiornamenti per tutti i problemi importanti), e XDebug recente non si compila nemmeno con questo php. Così sono finito con il passaggio al debugger DBG Il suo benchmarking php fornisce tempistiche per funzioni, metodi, moduli e persino linee.


2

Dovreste assolutamente controllare questo nuovo profiler php.

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

Ridefinisce il modo in cui i profiler php raccolgono e presentano il risultato. Invece di emettere solo un numero totale di chiamate di funzioni particolari e il tempo totale impiegato per eseguirla - PHP-SPX presenta l'intera sequenza temporale dell'esecuzione della richiesta in un modo perfettamente leggibile. Di seguito è la schermata della GUI che fornisce.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.