Alternative a gprof [chiuso]


166

Quali altri programmi fanno la stessa cosa di gprof?


2
a quali piattaforme sei interessato?
osgx,

2
Sono interessato a Linux.
neuromante


13
@Gregory - Sono propenso ad essere d'accordo, e forse dovrebbe contribuire con le sue risposte, 229 vs 6, tutte e 6 quelle risposte sono alle sue stesse domande ...
Jean-Bernard Pellerin

5
Come può questa domanda non essere costruttiva?
JohnTortugo

Risposte:


73

Valgrind ha un profiler per il conteggio delle istruzioni con un visualizzatore molto carino chiamato KCacheGrind . Come Mike Dunlavey raccomanda, Valgrind conta la frazione di istruzioni per le quali è in corso una procedura in pila, anche se mi dispiace dire che sembra confusa in presenza di una ricorsione reciproca. Ma il visualizzatore è molto bello e anni luce avanti gprof.


2
@Norman: ++ Quella confusione sulla ricorsione sembra endemica ai sistemi che hanno il concetto di propagare i tempi tra i nodi in un grafico. Inoltre, penso che il tempo dell'orologio a muro sia generalmente più utile dei tempi di istruzione della CPU e che le righe di codice (istruzioni di chiamata) siano più utili delle procedure. Se vengono prelevati campioni impilati a orari di orologio a muro casuali, il costo frazionario di una linea (o procedura o qualsiasi altra descrizione che si può fare) viene semplicemente stimato dalla frazione di campioni che lo esibiscono.
Mike Dunlavey,

1
... sto sottolineando le istruzioni di chiamata, ma si applica a qualsiasi istruzione. Se uno ha un collo di bottiglia dell'hotspot onesto alla bontà, come una sorta di bolla di una vasta gamma di numeri, le istruzioni di confronto / salto / scambio / incremento del circuito interno saranno nella parte superiore / inferiore di quasi ogni campione dello stack . Ma (soprattutto come software diventa grande e difficilmente qualsiasi routine ha molto tempo "auto") molti problemi in realtà sono le istruzioni di chiamata, chiedendo lavoro che, quando è chiaro quanto costa, non molto deve essere fatto.
Mike Dunlavey,

3
... Controllalo. Penso che siano quasi sulla buona strada: rotateright.com/zoom.html
Mike Dunlavey,

195

gprof (leggi l'articolo) esiste per ragioni storiche. Se pensi che ti aiuterà a trovare problemi di prestazioni, non è mai stato pubblicizzato come tale. Ecco cosa dice il documento:

Il pro fi lo può essere utilizzato per confrontare e valutare i costi di varie implementazioni.

Non dice che può essere usato per identificare le varie implementazioni da valutare, anche se implica che potrebbe, in circostanze speciali:

specialmente se si scopre che piccole parti del programma dominano il suo tempo di esecuzione.

Che dire dei problemi che non sono così localizzati? Quelli non contano? Non gettare aspettative su gprof che non sono mai state rivendicate per questo. È solo uno strumento di misurazione e solo delle operazioni associate alla CPU.

Prova questo invece.
Ecco un esempio di uno speedup 44x.
Ecco uno speedup 730x.
Ecco una dimostrazione video di 8 minuti.
Ecco una spiegazione delle statistiche.
Ecco una risposta alle critiche.

C'è una semplice osservazione sui programmi. In una data esecuzione, ogni istruzione è responsabile di una frazione del tempo complessivo (in particolare le callistruzioni), nel senso che se non fosse presente, il tempo non sarebbe trascorso. Durante quel periodo, l'istruzione è in pila **. Quando questo è compreso, puoi vedere che -

gprof incarna alcuni miti sulle prestazioni, come:

  1. quel campionamento del contatore di programmi è utile.
    È utile solo se si dispone di un collo di bottiglia dell'hotspot non necessario come una sorta di bolla di una vasta gamma di valori scalari. Non appena, ad esempio, lo si cambia in un ordinamento usando string-compare, rimane comunque un collo di bottiglia, ma il campionamento del contatore del programma non lo vedrà perché ora l'hotspot è in string-compare. D'altra parte, se si dovesse campionare il contatore del programma esteso (lo stack di chiamate), il punto in cui viene chiamato il confronto di stringhe, il ciclo di ordinamento, viene visualizzato chiaramente. In effetti, gprof è stato un tentativo di porre rimedio ai limiti del campionamento solo su PC.

  2. che le funzioni di temporizzazione sono più importanti della cattura di lunghe righe di codice.
    La ragione di questo mito è che gprof non è stato in grado di catturare campioni di stack, quindi cronometra le funzioni, conta le loro invocazioni e cerca di catturare il grafico delle chiamate. Tuttavia, una volta identificata una funzione costosa, è comunque necessario cercare al suo interno le linee responsabili del tempo. Se ci fossero campioni di stack che non avresti bisogno di guardare, quelle linee sarebbero sui campioni. (Una funzione tipica potrebbe avere 100 - 1000 istruzioni. Una chiamata di funzione è 1 istruzione, quindi qualcosa che individua chiamate costose è 2-3 ordini di grandezza più precisi.)

  3. che il grafico della chiamata è importante.
    Quello che devi sapere su un programma non è dove trascorre il suo tempo, ma perché. Quando trascorre del tempo in una funzione, ogni riga di codice nello stack fornisce un collegamento nella catena di ragionamento del perché è lì. Se riesci a vedere solo parte dello stack, puoi vedere solo una parte del motivo, quindi non puoi dire con certezza se quel tempo è effettivamente necessario. Cosa ti dice il grafico delle chiamate? Ogni arco indica che alcune funzioni A erano in procinto di chiamare alcune funzioni B per una frazione del tempo. Anche se A ha solo una di queste righe di codice che chiama B, quella riga fornisce solo una piccola parte del motivo. Se sei abbastanza fortunato, forse quella linea ha un motivo scarso. Di solito, è necessario vedere più righe simultanee per trovare una ragione scadente se è lì. Se A chiama B in più di un posto, allora ti dice anche meno.

  4. quella ricorsione è un problema complicato e confuso.
    Questo solo perché gprof e altri profiler percepiscono la necessità di generare un grafico di chiamata e quindi attribuire i tempi ai nodi. Se uno ha campioni dello stack, il costo nel tempo di ogni riga di codice che appare sui campioni è un numero molto semplice: la frazione di campioni su cui si trova. In caso di ricorsione, una determinata riga può apparire più di una volta su un campione. Non importa. Supponiamo che i campioni vengano prelevati ogni N ms e che la linea appaia su F% di essi (singolarmente o no). Se si può fare in modo che quella linea non richieda tempo (ad esempio cancellandola o ramificandola), quei campioni sparirebbero e il tempo verrebbe ridotto di F%.

  5. che l'accuratezza della misurazione del tempo (e quindi un gran numero di campioni) è importante.
    Pensaci per un secondo. Se una riga di codice è su 3 campioni su cinque, quindi se si potesse sparare come una lampadina, sarebbe circa il 60% in meno di tempo che verrebbe utilizzato. Ora, sai che se avessi preso 5 diversi campioni, avresti potuto vederlo solo 2 volte, o fino a 4. Quindi la misurazione del 60% è più simile a un intervallo generale dal 40% all'80%. Se fosse solo il 40%, diresti che non vale la pena risolvere il problema? Quindi qual è l'accuratezza del momento preciso, quando quello che vuoi davvero è trovare i problemi ? 500 o 5000 campioni avrebbero misurato il problema con maggiore precisione, ma non lo avrebbero trovato più accuratamente.

  6. che il conteggio delle invocazioni di istruzioni o funzioni è utile.
    Supponiamo che tu sappia che una funzione è stata chiamata 1000 volte. Puoi dire da ciò che frazione di tempo costa? Devi anche sapere quanto tempo ci vuole per correre, in media, moltiplicarlo per il conteggio e dividere per il tempo totale. Il tempo medio di chiamata può variare da nanosecondi a secondi, quindi il conteggio da solo non dice molto. Se ci sono campioni di stack, il costo di una routine o di qualsiasi istruzione è solo la frazione di campioni su cui si trova. Quella frazione di tempo è ciò che in linea di principio potrebbe essere risparmiato se la routine o l'affermazione non si realizzasse in pochissimo tempo, quindi questa è la relazione più diretta con la performance.

  7. che i campioni non devono essere prelevati quando bloccati
    Le ragioni di questo mito sono duplici: 1) che il campionamento su PC non ha senso quando il programma è in attesa, e 2) la preoccupazione per l'accuratezza dei tempi. Tuttavia, per (1) il programma potrebbe essere in attesa di qualcosa che ha richiesto, come I / O di file, che è necessario conoscere e quali campioni dello stack rivelano. (Ovviamente si desidera escludere campioni in attesa dell'input dell'utente.) Per (2) se il programma è in attesa semplicemente a causa della concorrenza con altri processi, ciò presumibilmente accade in modo abbastanza casuale mentre è in esecuzione. Quindi, mentre il programma potrebbe richiedere più tempo, ciò non avrà un grande effetto sulla statistica che conta, la percentuale di tempo in cui le istruzioni sono in pila.

  8. che il "tempo di sé" è importante Il
    tempo di sé ha senso solo se si sta misurando a livello di funzione, non a livello di linea, e si ritiene di aver bisogno di aiuto per discernere se il tempo di funzione va in un calcolo puramente locale rispetto alle routine chiamate. Se riepilogando a livello di linea, una linea rappresenta il tempo autonomo se si trova alla fine della pila, altrimenti rappresenta il tempo inclusivo. In entrambi i casi, ciò che costa è la percentuale di campioni dello stack su cui si trova, in modo che lo localizzi in entrambi i casi.

  9. che i campioni devono essere prelevati ad alta frequenza
    Ciò deriva dall'idea che un problema di prestazioni potrebbe essere ad azione rapida e che i campioni devono essere frequenti per colpirlo. Ma, se il problema costa, 20%, ad esempio, su un tempo di esecuzione totale di 10 sec (o qualsiasi altra cosa), ogni campione in quel tempo totale avrà una probabilità del 20% di colpirlo, non importa se si verifica il problema in un singolo pezzo come questo
    .....XXXXXXXX...........................
    .^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^(20 campioni, 4 risultati)
    o in molti piccoli pezzi come questo
    X...X...X.X..X.........X.....X....X.....
    .^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^(20 campioni, 3 risultati)
    Ad ogni modo, il numero di risultati sarà in media circa 1 su 5, indipendentemente dal numero di campioni prelevati, oppure quanto pochi. (Media = 20 * 0,2 = 4. Deviazione standard = +/- sqrt (20 * 0,2 * 0,8) = 1,8.)

  10. che stai cercando di trovare il collo
    di bottiglia come se ce ne fosse solo uno. Considera la seguente sequenza temporale di esecuzione: vxvWvzvWvxvWvYvWvxvWv.vWvxvWvYvW
    consiste in un vero lavoro utile, rappresentato da .. Ci sono problemi di prestazioni che vWxYzrichiedono rispettivamente 1/2, 1/4, 1/8, 1/16, 1/32 del tempo. Il campionamento lo trova vfacilmente. Viene rimosso, lasciando
    xWzWxWYWxW.WxWYW
    Ora il programma impiega la metà del tempo per essere eseguito, e ora Wimpiega la metà del tempo, e si trova facilmente. Viene rimosso, lasciando
    xzxYx.xY
    Questo processo continua, rimuovendo ogni volta il più grande, in percentuale, problema di prestazioni, fino a quando non si trova nulla da rimuovere. Ora l'unica cosa eseguita è ., che viene eseguita in 1/32 del tempo utilizzato dal programma originale. Questo è l' effetto di ingrandimento, per cui la rimozione di qualsiasi problema rende il resto più grande, in percentuale, perché il denominatore è ridotto.
    Un altro punto cruciale è che ogni singolo problema deve essere trovato - mancando nessuno dei 5. Qualsiasi problema non trovato e risolto riduce notevolmente il rapporto di accelerazione finale. Solo trovarne alcuni, ma non tutti, non è "abbastanza buono".

AGGIUNTO: Vorrei solo sottolineare un motivo per cui gprof è popolare: viene insegnato, presumibilmente perché è gratuito, facile da insegnare ed è in circolazione da molto tempo. Una rapida ricerca su Google individua alcune istituzioni accademiche che insegnano (o sembrano) a:

berkeley bu clemson colorado duca Earlham fsu indiana mit msu ncsa.illinois ncsu nyu ou princeton psu stanford ucsd umd umich utah utexas utk wustl

** Con l'eccezione di altri modi per richiedere il lavoro da svolgere, ciò non lascia traccia del perché , ad esempio tramite la pubblicazione di messaggi.


3
@Norman: ho creato un profiler basato su questo, in C per DOS, intorno al '93. L'ho chiamato ancora un altro analizzatore di prestazioni e l'ho dimostrato in giro durante le riunioni IEEE, ma è andata così. C'è un prodotto di RotateRight chiamato Zoom che non è troppo lontano. Su * nix, pstack è buono per farlo manualmente. La mia lista di cose da fare per lavoro (farmacometria su Windows) è lunga circa un chilometro e preclude progetti divertenti, per non parlare della famiglia. Questo potrebbe essere utile: stackoverflow.com/questions/1777669/...
Mike Dunlavey

6
Ho sempre trovato i profiler non così utili per correggere il codice lento, e invece ho usato frammenti selettivi di codice di debug per misurare il tempo impiegato da un gruppo di istruzioni di mia scelta, spesso aiutato da alcune piccole macro o altro. Non ho mai impiegato troppo tempo per trovare il colpevole, ma sono sempre stato imbarazzato dal mio approccio "pelli d'orso e coltelli di pietra" quando "tutti gli altri" (per quanto ne so) usano gli strumenti fantasiosi. Grazie per avermi mostrato perché non ho mai potuto ottenere le informazioni di cui avevo bisogno dal profiler. Questa è una delle idee più importanti che ho visto su SO. Molto bene!
Wayne Conrad,

7
@osgx: non intendo strappare nulla. È come una vecchia automobile preferita, semplice e robusta, ma ci sono cose che non fanno, e dobbiamo essere consapevoli di quelle, e non solo, dobbiamo svegliarci dai miti. Apprezzo che su alcune piattaforme potrebbe essere difficile ottenere campioni di stack, ma se un problema è tale che gprof non lo troverà, il fatto che sia l'unico strumento è un piccolo conforto.
Mike Dunlavey,

2
@Andrew: ... e se quel motivo si applica ad una frazione significativa di campioni (come più di 1), allora le righe di codice che potrebbero eliminare quell'attività sono su quei campioni. Un grafico può darti un suggerimento , ma un numero non elevato di campioni di stack te li mostrerà semplicemente.
Mike Dunlavey,

2
@Matt: esempi di problemi di prestazioni di I / O trovati in questo modo: 1) stampa dei messaggi di log su un file o sulla console, che erroneamente si riteneva insignificante. 2) Conversione tra testo e doppio in IO numerico. 3) IO sotterraneo che estrae stringhe internazionalizzate durante l'avvio, le stringhe che risulta non hanno bisogno di essere internazionalizzate. Ho colto molti esempi come questi.
Mike Dunlavey,

63

Dal momento che non ho visto nulla su perfquale sia uno strumento relativamente nuovo per la creazione del profilo del kernel e delle applicazioni utente su Linux, ho deciso di aggiungere queste informazioni.

Prima di tutto, questo è un tutorial sulla profilazione di Linux conperf

Puoi usare perfse il tuo kernel Linux è maggiore di 2.6.32 o oprofilese è più vecchio. Entrambi i programmi non richiedono da te per strumentare il tuo programma (come gprofrichiede). Tuttavia, al fine di ottenere correttamente il grafico delle chiamate, perfè necessario creare il programma con -fno-omit-frame-pointer. Ad esempio: g++ -fno-omit-frame-pointer -O2 main.cpp.

Puoi vedere l'analisi "live" della tua applicazione con perf top:

sudo perf top -p `pidof a.out` -K

Oppure puoi registrare i dati sulle prestazioni di un'applicazione in esecuzione e analizzarli successivamente:

1) Per registrare i dati sulle prestazioni:

perf record -p `pidof a.out`

o per registrare per 10 secondi:

perf record -p `pidof a.out` sleep 10

o per registrare con il grafico delle chiamate ()

perf record -g -p `pidof a.out` 

2) Analizzare i dati registrati

perf report --stdio
perf report --stdio --sort=dso -g none
perf report --stdio -g none
perf report --stdio -g

Oppure puoi registrare i dati di performance di un'applicazione e analizzarli dopo semplicemente avviando l'applicazione in questo modo e aspettando che esca:

perf record ./a.out

Questo è un esempio di profilazione di un programma di test

Il programma di test è nel file main.cpp (metterò main.cpp nella parte inferiore del messaggio):

Lo compilo in questo modo:

g++ -m64 -fno-omit-frame-pointer -g main.cpp -L.  -ltcmalloc_minimal -o my_test

Uso libmalloc_minimial.sopoiché è compilato -fno-omit-frame-pointermentre libc malloc sembra essere compilato senza questa opzione. Quindi eseguo il mio programma di test

./my_test 100000000 

Quindi registro i dati sulle prestazioni di un processo in esecuzione:

perf record -g  -p `pidof my_test` -o ./my_test.perf.data sleep 30

Quindi analizzo il carico per modulo:

perf report --stdio -g none --sort comm, dso -i ./my_test.perf.data

# Overhead  Command                 Shared Object
# ........  .......  ............................
#
    70.06%  my_test  my_test
    28.33%  my_test  libtcmalloc_minimal.so.0.1.0
     1.61%  my_test  [kernel.kallsyms]

Quindi viene analizzato il carico per funzione:

perf report --stdio -g none -i ./my_test.perf.data | c ++ filt

# Overhead  Command                 Shared Object                       Symbol
# ........  .......  ............................  ...........................
#
    29.30%  my_test  my_test                       [.] f2(long)
    29.14%  my_test  my_test                       [.] f1(long)
    15.17%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator new(unsigned long)
    13.16%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator delete(void*)
     9.44%  my_test  my_test                       [.] process_request(long)
     1.01%  my_test  my_test                       [.] operator delete(void*)@plt
     0.97%  my_test  my_test                       [.] operator new(unsigned long)@plt
     0.20%  my_test  my_test                       [.] main
     0.19%  my_test  [kernel.kallsyms]             [k] apic_timer_interrupt
     0.16%  my_test  [kernel.kallsyms]             [k] _spin_lock
     0.13%  my_test  [kernel.kallsyms]             [k] native_write_msr_safe

     and so on ...

Quindi vengono analizzate le catene di chiamata:

perf report --stdio -g graph -i ./my_test.perf.data | c ++ filt

# Overhead  Command                 Shared Object                       Symbol
# ........  .......  ............................  ...........................
#
    29.30%  my_test  my_test                       [.] f2(long)
            |
            --- f2(long)
               |
                --29.01%-- process_request(long)
                          main
                          __libc_start_main

    29.14%  my_test  my_test                       [.] f1(long)
            |
            --- f1(long)
               |
               |--15.05%-- process_request(long)
               |          main
               |          __libc_start_main
               |
                --13.79%-- f2(long)
                          process_request(long)
                          main
                          __libc_start_main

    15.17%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator new(unsigned long)
            |
            --- operator new(unsigned long)
               |
               |--11.44%-- f1(long)
               |          |
               |          |--5.75%-- process_request(long)
               |          |          main
               |          |          __libc_start_main
               |          |
               |           --5.69%-- f2(long)
               |                     process_request(long)
               |                     main
               |                     __libc_start_main
               |
                --3.01%-- process_request(long)
                          main
                          __libc_start_main

    13.16%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator delete(void*)
            |
            --- operator delete(void*)
               |
               |--9.13%-- f1(long)
               |          |
               |          |--4.63%-- f2(long)
               |          |          process_request(long)
               |          |          main
               |          |          __libc_start_main
               |          |
               |           --4.51%-- process_request(long)
               |                     main
               |                     __libc_start_main
               |
               |--3.05%-- process_request(long)
               |          main
               |          __libc_start_main
               |
                --0.80%-- f2(long)
                          process_request(long)
                          main
                          __libc_start_main

     9.44%  my_test  my_test                       [.] process_request(long)
            |
            --- process_request(long)
               |
                --9.39%-- main
                          __libc_start_main

     1.01%  my_test  my_test                       [.] operator delete(void*)@plt
            |
            --- operator delete(void*)@plt

     0.97%  my_test  my_test                       [.] operator new(unsigned long)@plt
            |
            --- operator new(unsigned long)@plt

     0.20%  my_test  my_test                       [.] main
     0.19%  my_test  [kernel.kallsyms]             [k] apic_timer_interrupt
     0.16%  my_test  [kernel.kallsyms]             [k] _spin_lock
     and so on ...

Quindi a questo punto sai dove il tuo programma passa il tempo.

E questo è main.cpp per il test:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

time_t f1(time_t time_value)
{
  for (int j =0; j < 10; ++j) {
    ++time_value;
    if (j%5 == 0) {
      double *p = new double;
      delete p;
    }
  }
  return time_value;
}

time_t f2(time_t time_value)
{
  for (int j =0; j < 40; ++j) {
    ++time_value;
  }
  time_value=f1(time_value);
  return time_value;
}

time_t process_request(time_t time_value)
{

  for (int j =0; j < 10; ++j) {
    int *p = new int;
    delete p;
    for (int m =0; m < 10; ++m) {
      ++time_value;
    }
  }
  for (int i =0; i < 10; ++i) {
    time_value=f1(time_value);
    time_value=f2(time_value);
  }
  return time_value;
}

int main(int argc, char* argv2[])
{
  int number_loops = argc > 1 ? atoi(argv2[1]) : 1;
  time_t time_value = time(0);
  printf("number loops %d\n", number_loops);
  printf("time_value: %d\n", time_value );

  for (int i =0; i < number_loops; ++i) {
    time_value = process_request(time_value);
  }
  printf("time_value: %ld\n", time_value );
  return 0;
}

Ho appena fatto il tuo esempio e ho preso 5 colpi di stack. Ecco cosa hanno scoperto: il 40% (approssimativamente) del tempo f1chiamava delete. Il 40% (all'incirca) del tempo process_requestchiamava delete. Una buona parte del resto è stata spesa new. Le misurazioni sono approssimative, ma gli hotspot sono individuati con precisione.
Mike Dunlavey,

Che cos'è un stackshot? È quello che pstackemette?

2
As in my answer, you run it under a debugger and hit ^C at a random time and capture the stack trace. 1) Penso che la tua tecnica non sia utile quando devi analizzare i problemi di prestazioni per un programma in esecuzione sul server del tuo cliente. 2) Non sono sicuro di come applicare questa tecnica per ottenere informazioni per un programma con molti thread che gestiscono richieste diverse. Voglio dire quando il quadro generale è piuttosto complicato.

2
Per quanto riguarda il n. 1. A volte i clienti chiamano e dicono che il tuo programma funziona lentamente. Non puoi dirlo subito the problem is outside your code, vero? Dal momento che potresti aver bisogno di alcune informazioni per supportare il tuo punto. In questa situazione a un certo punto potrebbe essere necessario creare un profilo dell'applicazione. Non puoi semplicemente chiedere al tuo cliente di avviare gdb e premere ^ C e ottenere stack di chiamate. Questo era il mio punto. Questo è un esempio di spielwiese.fontein.de/2012/2012/22/… . Ho avuto questo problema e la profilazione mi ha aiutato molto.

2
Per quanto riguarda il n. 2. Semplificare è un buon approccio, sono d'accordo. A volte funziona. Se un problema di prestazioni si verifica solo sul server di un cliente e non è possibile riprodurlo sul server, i profili sono utili.

21

Prova OProfile . È uno strumento molto migliore per la profilazione del codice. Vorrei anche suggerire Intel VTune .

I due strumenti di cui sopra possono ridurre il tempo trascorso in una particolare riga di codice, annotare il codice, mostrare l'assemblaggio e la quantità di istruzioni specifiche. Oltre alla metrica temporale, puoi anche eseguire query su contatori specifici, ad esempio hit della cache, ecc.

A differenza di gprof, puoi profilare qualsiasi processo / binario in esecuzione sul tuo sistema usando uno dei due.


2
Come menzionato anche nella risposta valgrind, Zoom from RotateRight ( rotateright.com ) offre un'interfaccia molto più gradevole e consente la creazione di profili in remoto.
JanePhanie,

non mi piaceva il profilo, sembrava casuale
Matt Joiner,

@Matt qualche punto particolare?
Anycorn

Non è stato in grado di far fronte a più di 10 secondi di esecuzione prima di generare overflow stat, l'output non è stato particolarmente utile e la documentazione è terribile.
Matt Joiner,

1
@Il OProfile: ARM, POWER, ia64, ...
Anycorn



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.