2012-06-03 14 views
6

Ho appena iniziato a utilizzare gli strumenti di performance di Google (google-perftools e libgoogle-perftools4 pacchetti di Ubuntu), giuro che sto googling per circa un giorno e non ho trovato una risposta !! Il problema è che non ottengo il risultato per TUTTE le mie funzioni con il profilo della CPU. Questo è il mio codice:Come utilizzare Google strumenti Potenza

#include "gperftools/profiler.h" 
#include <iostream> 
#include <math.h> 
using namespace std; 
void bar() 
{ 
     int a,b,c,d,j,k; 
     a=0; 
     int z=0; 
     b = 1000; 
     while(z < b) 
     { 
       while (a < b) 
       { 
         d = sin(a); 
         c = cos(a); 
         j = tan(a); 
         k = tan(a); 
         k = d * c + j *k; 
         a++; 
       } 
       a = 0; 
       z++; 
     } 
} 
void foo() 
{ 
     cout << "hey " << endl; 
} 

int main() 
{ 
     ProfilerStart("/home/mohammad/gperf/dump.txt"); 

     int a = 1000; 
     while(a--){foo();} 
     bar(); 
     ProfilerFlush(); 
     ProfilerStop(); 
} 

Compilato come g++ test.cc -lprofiler -o a.out

è così che esegue il codice:

CPUPROFILE=dump.txt ./a.out 

Inoltre ho provato questo:

CPUPROFILE_FREQUENCY=10000 LD_PRELOAD=/usr/local/lib/libprofiler.so.0.3.0 CPUPROFILE=dump.txt ./a.out 

E questo è quello che ottengo da google-pprof --text a.out dump.txt:

Using local file ./a.out. 
Using local file ./dump.txt. 
Total: 22 samples 
8 36.4% 36.4%  8 36.4% 00d8cb04 
6 27.3% 63.6%  6 27.3% bar 
3 13.6% 77.3%  3 13.6% __cos (inline) 
2 9.1% 86.4%  2 9.1% 00d8cab4 
1 4.5% 90.9%  1 4.5% 00d8cab6 
1 4.5% 95.5%  1 4.5% 00d8cb06 
1 4.5% 100.0%  1 4.5% __write_nocancel 
0 0.0% 100.0%  3 13.6% __cos 

Ma non ci sono informazioni sulla funzione foo!

mia informazioni di sistema: ubuntu 12.04 g ++ 4.6.3

Questo è tutto!

+1

Hai detto che hai provato "CPUPROFILE_FREQUENC = 10000" ma che manca una Y, quindi se reale (e ignorato) allora potresti non avere abbastanza campioni per far apparire il piccolo foo. – mgkrebbs

+0

Stai guardando il tempo della CPU, non il tempo dell'orologio. La quantità di tempo CPU 'foo' usata è quasi nulla. Tutto ciò che fa è chiamare le funzioni di libreria che eseguono l'I/O e gli esempi di CPU non si verificano durante l'I/O. –

risposta

9

TL; DR: foo è veloce e piccolo per ottenere eventi di profilo, eseguirlo 100 volte in più. L'impostazione della frequenza era con errore di battitura e pprof non campionerà più spesso di CONFIG_HZ (in genere 250). È preferibile passare al più moderno profiler Linux perf (tutorial from its authors, wikipedia).

Versione lunga:

La funzione foo è troppo breve e semplice - basta chiamare due funzioni. Compilato il test con g++ test.cc -lprofiler -o test.s -S -g, con filtraggio di test.s con c++filt programma per rendere i nomi C++ leggibile:

foo(): 
.LFB972: 
     .loc 1 27 0 
     pushq %rbp 
     movq %rsp, %rbp 
     .loc 1 28 0 
     movl $.LC0, %esi 
     movl std::cout, %edi 
     call std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) 
     movl std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&), %esi 
     movq %rax, %rdi 
     call std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&)) 
     .loc 1 29 0 
     popq %rbp 
     ret 
.LFE972: 
     .size foo(), .-foo() 

Così, per vederlo nella scheda è necessario eseguire foo per più volte, cambiando int a = 1000; in principale per qualcosa di molto più grande , come 10000 o meglio 100000 (come ho fatto io per il test).

Inoltre, è possibile correggere l'errore "CPUPROFILE_FREQUENC=10000" per correggere CPUPROFILE_FREQUENCY (notare lo Y). Devo dire che 10000 è un'impostazione troppo alta per CPUPROFILE_FREQUENCY, perché di solito può generare solo 1000 o 250 eventi al secondo a seconda della configurazione del kernel CONFIG_HZ (la maggior parte dei kernel 3.x ha 250, controllare grep CONFIG_HZ= /boot/config*). E l'impostazione per CPUPROFILE_FREQUENCY in pprof di default è 100.

ho provato diversi valori di CPUPROFILE_FREQUENCY: 100000, 10000, 1000, 250 con script bash su Ubuntu 14.04

for a in 100000 100000 10000 10000 1000 1000 300 300 250 250; do 
    echo -n "$a "; 
    CPUPROFILE_FREQUENCY=$a CPUPROFILE=dump$a.txt ./test >/dev/null; 
done 

E i risultati sono stati gli stessi 120-140 eventi e tempo di esecuzione di ogni ./test intorno 0.5 secondi, in modo da cpuprofiler google-perftools non possono fare più eventi al secondo per singolo thread, che insieme CONFIG_HZ nel kernel (il mio ne ha 250).

100000 PROFILE: interrupts/evictions/bytes = 124/1/6584 
100000 PROFILE: interrupts/evictions/bytes = 134/0/7864 
10000 PROFILE: interrupts/evictions/bytes = 125/0/7488 
10000 PROFILE: interrupts/evictions/bytes = 123/0/6960 
1000 PROFILE: interrupts/evictions/bytes = 134/0/6264 
1000 PROFILE: interrupts/evictions/bytes = 125/2/7272 
300 PROFILE: interrupts/evictions/bytes = 137/2/7984 
300 PROFILE: interrupts/evictions/bytes = 126/0/7216 
250 PROFILE: interrupts/evictions/bytes = 123/3/6680 
250 PROFILE: interrupts/evictions/bytes = 137/2/7352 

con a = 1000 foo e cout delle funzioni originali corre troppo veloce per ottenere ogni caso profilazione (anche su 250 eventi/s) su di essi in ogni corsa, in modo da avere nessun foo, né le funzioni di Input/Output . In piccola quantità di piste, il __write_nocancel può ottenuto evento di campionamento, quindi foo e I/formare funzioni O libstdC++ saranno segnalati (da qualche parte non nella parte superiore, in modo da utilizzare --text possibilità di pprof o google-pprof) con conteggio degli eventi pari a zero di sé, e conteggio degli eventi non-zero bambino:

.... 
    1 0.9% 99.1%  1 0.9% __write_nocancel 
.... 
    0 0.0% 100.0%  1 0.9% _IO_new_file_overflow 
    0 0.0% 100.0%  1 0.9% _IO_new_file_write 
    0 0.0% 100.0%  1 0.9% __GI__IO_putc 
    0 0.0% 100.0%  1 0.9% foo 
    0 0.0% 100.0%  1 0.9% new_do_write 
    0 0.0% 100.0%  1 0.9% std::endl 
    0 0.0% 100.0%  1 0.9% std::ostream::put 

Con a=100000, foo è ancora troppo breve e veloce per ottenere propri eventi, ma funzioni di I/O ha ottenuto diversi. Questa è la lista che grepped dalla lunga --text uscita:

34 24.6% 24.6%  34 24.6% __write_nocancel 

    1 0.7% 95.7%  35 25.4% __GI__IO_fflush 
    1 0.7% 96.4%  1 0.7% __GI__IO_putc 
    1 0.7% 97.8%  2 1.4% std::operator<< 
    1 0.7% 98.6%  36 26.1% std::ostream::flush 
    1 0.7% 99.3%  2 1.4% std::ostream::put 
    0 0.0% 100.0%  34 24.6% _IO_new_file_sync 
    0 0.0% 100.0%  34 24.6% _IO_new_file_write 
    0 0.0% 100.0%  40 29.0% foo 

    0 0.0% 100.0%  34 24.6% new_do_write 

    0 0.0% 100.0%  2 1.4% std::endl 

funzioni con zero propri contatori visibili solo grazie alla pprof capacità di catene leggere di chiamata (si sa che chiama le funzioni che ha ottenuto campione, se informazioni telaio non viene omesso) .

posso anche consigliare più capaci più moderne, (sia software che hardware eventi, fino a 5 kHz o più; sia in user-space e kernel profilazione) e profiler meglio supportato, il Linux perf profiler (tutorial from its authors, wikipedia) .

Non ci sono risultati da perf con a=10000:

$ perf record ./test3 >/dev/null 
... skip some perf's spam about inaccessibility of kernel symbols 
... note the 3 kHz frequency here VVVV 
Lowering default frequency rate to 3250. 
Please consider tweaking /proc/sys/kernel/perf_event_max_sample_rate. 
[ perf record: Woken up 1 times to write data ] 
[ perf record: Captured and wrote 0.078 MB perf.data (~3386 samples) ] 

Per vedere rapporto di testo da file di output perf.data userò meno (perché perf report da inizio di default del browser profilo interattivo):

$ perf report |less 
... skip some extra info about the machine, kernel, and perf starting command 
# Samples: 1K of event 'cycles' 
# Event count (approx.): 1155264208 
# Overhead Command Shared Object   Symbol 
    41.94% test3 libm-2.19.so   [.] __tan_sse2                                          
    16.95% test3 libm-2.19.so   [.] __sin_sse2  
    13.40% test3 libm-2.19.so   [.] __cos_sse2                                          
    4.93% test3 test3    [.] bar()                                           
    2.90% test3 libc-2.19.so   [.] __GI___libc_write  
.... 
    0.20% test3 test3    [.] foo()                                           

Oppure perf report -n | less per visualizzare contatori evento (campione) non elaborati:

# Overhead  Samples Command  Shared Object 
    41.94%   663 test3 libm-2.19.so   [.] __tan_sse2                                          
    16.95%   268 test3 libm-2.19.so   [.] __sin_sse2 
    13.40%   212 test3 libm-2.19.so   [.] __cos_sse2                                          
    4.93%   78 test3 test3    [.] bar()                                           
    2.90%   62 test3 libc-2.19.so   [.] __GI___libc_write  
.... 
    0.20%    4 test3 test3    [.] foo()                                           
0

Prova a impostare LD_PRELOAD a poco

LD_PRELOAD =/usr/local/lib/libprofiler.so

E looks like there are problems quando passa una libreria condivisa che non si esaurisce nel suffisso .so.

Problemi correlati