Non c'è dubbio che il test sia parte integrante e uno degli aspetti più importanti del processo di sviluppo del software. E per test, non intendiamo solo testare il codice per rilevare eventuali bug - ovviamente, il rilevamento dei bug è importante poiché nessuno vorrebbe che il proprio software fosse buggato - anche le prestazioni del codice contano ugualmente in questi giorni.
Se suddiviso fino all'ultimo bit, il test delle prestazioni verifica in modo efficace quanto tempo sta consumando un particolare pezzo di codice, ad esempio una funzione. Come di consueto, una funzione o un gruppo di funzioni può corrispondere a una delle tante caratteristiche di un software. Quindi, se attraverso i test delle prestazioni riusciamo a migliorare le prestazioni di queste funzioni nel codice, le prestazioni complessive del software migliorano.
Se sei un programmatore che scrive codice nel linguaggio di programmazione C, Pascal o Fortran77 e utilizza Linux come piattaforma di sviluppo, sarai felice di sapere che esiste un potente strumento attraverso il quale puoi controllare le prestazioni del tuo codice:lo strumento in questione è Gprof. In questo tutorial, discuteremo i dettagli su come scaricare, installare e utilizzare questo strumento.
Prima di andare avanti, tieni presente che tutti gli esempi e le istruzioni menzionati in questo tutorial sono stati testati su Ubuntu 14.04LTS e la versione di Gprof utilizzata è la 2.24.
Cos'è Gprof?
Allora, cos'è esattamente Gprof? Secondo la documentazione ufficiale dello strumento, fornisce agli utenti un profilo di esecuzione dei loro programmi C, Pascal o Fortran77. Quello che fa fondamentalmente Gprof è, calcola la quantità di tempo speso in ogni routine o funzione. "Successivamente, questi tempi vengono propagati lungo i bordi del grafico delle chiamate. I cicli vengono scoperti e vengono effettuate chiamate in un ciclo per condividere il tempo del ciclo."
Se tutto questo suona un po' confuso a questo punto (specialmente la parte tra virgolette), non preoccuparti, poiché chiariremo le cose attraverso un esempio. Quindi, continua a leggere.
Scarica e installa Gprof
Per prima cosa controlla se lo strumento è già installato sul tuo sistema. Per fare ciò, esegui semplicemente il seguente comando in un terminale.
$ gprof
Se ricevi un errore del tipo:
$ a.out:nessun file o directory di questo tipo
quindi questo significherebbe che lo strumento è già installato. Altrimenti puoi installarlo usando il seguente comando:
$ apt-get install binutils
Utilizzo Gprof
Inutile dire che il modo migliore per comprendere uno strumento come Gprof è attraverso un esempio pratico. Quindi, inizieremo con un programma in linguaggio C, di cui faremo il profilo tramite Gprof. Ecco il programma:
//test_gprof.c
#include
void func4(void)
{
printf("\n Inside func4() \n");
for(int count=0;count<=0XFFFF;count++);
}
void func3(void)
{
printf("\n Inside func3() \n");
for(int count=0;count<=0XFFFFFFF;count++);
}
void func2(void)
{
printf("\n Inside func2() \n");
for(int count=0;count<=0XFFF;count++ );
func3();
}
void func1(void)
{
printf("\n Inside func1() \n");
for(int count=0;count<=0XFFFFFF;count++);
func2();
}
int main(void)
{
printf("\n main() inizia...\n");
for(int count=0;count<=0XFFFFF;count++);
func1();
func4();
printf("\n main() finisce...\n");
return 0;
}
Tieni presente che il codice mostrato sopra (test_gprof.c ) è scritto specificamente per spiegare Gprof - non è tratto da nessun progetto di vita reale.
Ora, andando avanti, il passo successivo è compilare questo codice usando gcc. Nota che idealmente avrei compilato il codice sopra usando il seguente comando:
$ gcc -Wall -std=c99 test_gprof.c -o test_gprof
Ma dato che dobbiamo profilare il codice usando Gprof, dovrò usare il -pg opzione della riga di comando fornita dal compilatore gcc. Quindi, il comando diventa:
$ gcc -Wall -std=c99 -pg test_gprof.c -o test_gprof
Se dai un'occhiata alla pagina man di gcc, ecco cosa dice sul -pg opzione:
"Genera codice aggiuntivo per scrivere informazioni sul profilo adatte al programma di analisi gprof. Devi utilizzare questa opzione durante la compilazione dei file di origine su cui desideri dati e devi utilizzarla anche durante il collegamento."
Ora, tornando al comando precedente, dopo che è stato eseguito con successo, produrrà un binario chiamato test_gprof nell'uscita. Il prossimo passo è lanciare quell'eseguibile. Ecco come ho avviato il file binario nel mio caso:
$ ./test_gprof
Una volta eseguito il comando, vedrai un file chiamato gmon.out verrà generato nella directory di lavoro corrente.
$ ls gmon*
gmon.out
È questo file che contiene tutte le informazioni che lo strumento Gprof richiede per produrre dati di profilazione leggibili dall'uomo. Quindi, ora usa lo strumento Gprof nel modo seguente:
$ gprof test_gprof gmon.out> profile-data.txt
Fondamentalmente, la sintassi generica di questo comando è:
$ gprof [nome-eseguibile] gmon.out> [nome-del-file-che-conterrà-dati-di-profilazione]
Ora, prima di vedere le informazioni, profile-data.txt contiene, vale la pena ricordare che l'output leggibile dall'uomo prodotto da Gprof è diviso in due parti:profilo piatto e grafico delle chiamate. Ecco cosa dice la pagina man di Gprof sulle informazioni in queste due sezioni:
"Il profilo piatto mostra quanto tempo il tuo programma ha trascorso in ciascuna funzione e quante volte tale funzione è stata chiamata. Se vuoi semplicemente sapere quali funzioni bruciano la maggior parte dei cicli, è riportato in modo conciso qui."
"Il grafico delle chiamate mostra, per ciascuna funzione, quali funzioni l'ha chiamata, quali altre funzioni ha chiamato e quante volte. C'è anche una stima di quanto tempo è stato speso nelle subroutine di ciascuna funzione. Questo può suggerire luoghi in cui potresti provare a eliminare le chiamate di funzione che richiedono molto tempo."
Grazie a queste informazioni, ora sarai in una posizione migliore per comprendere i dati presenti nel tuo file di output di profilazione (profile-data.txt nel mio caso). Ecco il profilo piatto nel mio caso:
Profilo piatto:
Ogni campione conta come 0,01 secondi.
% auto totale cumulativo
tempo secondi secondi chiamate ms/chiamata ms/nome chiamata
96,43 0.81 0.81 1 810.00 810.00 func3
3.57 0.84 0.03 1 30.00 840.00 func1
0.00 0.84 0.00 1 0.00 810.00 func2
0.00 0.84 0.00 1 0.0 func400pre 1.0.0
Ed ecco cosa significa ogni campo:
Andando avanti, ecco il grafico delle chiamate nel mio caso:
Grafico delle chiamate (spiegazione seguente)
granularità:ogni hit campione copre 4 byte per l'1,19% di 0,84 secondi
indice % tempo self bambini chiamati per nome
0.03 0.81 1/1 principale [2]
[1] 100.0 0.03 0.81 1 func1 [1]
0.00 0.81 1/1 func2 [3]
-- ----------------------------------------------
[2] 100.0 0.00 0.84 principale [2]
0.03 0.81 1/1 func1 [1]
0.00 0.00 1/1 func4 [5]
---- ----------------------------------------------------------
0.00 0.81 1 /1 func1 [1]
[3] 96,4 0,00 0,81 1 func2 [3]
0,81 0,00 1/1 func3 [4]
------------ -----------------------------------
0.81 0.00 1/1 func2 [3]
[4] 96,4 0,81 0,00 1 func3 [4]
--------------------------------- ----------- ---
0.00 0.00 1/1 principale [2]
[5] 0.0 0.00 0.00 1 func4 [5]Le schermate seguenti spiegano il grafico delle chiamate di informazioni che contiene:
Se ti stai chiedendo la fonte degli screenshot di cui sopra, lascia che ti dica che tutte queste informazioni sono presenti nel file di output che contiene le informazioni di profilazione, incluso il profilo piatto e il grafico delle chiamate. Nel caso in cui desideri che queste informazioni vengano omesse dall'output, puoi utilizzare -b opzione fornita da Gprof.
Conclusione
Inutile dire che qui abbiamo appena scalfito la superficie, poiché Gprof offre molte funzionalità (basta dare un'occhiata alla sua pagina man). Tuttavia, qualunque cosa abbiamo trattato qui dovrebbe essere sufficiente per iniziare. Nel caso in cui utilizzi già Gprof e desideri condividere qualcosa relativo allo strumento con tutti qui, inserisci un commento qui sotto.