2010-06-02 5 views
5

Ho un programma che desidero profilare con gprof. Il problema (apparentemente) è che usa le prese. Così ottengo cose del genere:Utilizzo di gprof con socket

::select(): Interrupted system call 

Ho colpito questo problema un po 'di tempo fa, ho rinunciato e sono andato avanti. Ma mi piacerebbe davvero essere in grado di profilare il mio codice, usando gprof se possibile. Cosa posso fare? C'è un'opzione gprof che mi manca? Un'opzione presa? Gprof è totalmente inutile in presenza di questi tipi di chiamate di sistema? In tal caso, esiste un'alternativa valida?

EDIT: Piattaforma:

  • Linux 2.6 (x64)
  • GCC 4.4.1
  • gprof 2,19
+0

Penso che si dovrebbe anche parlare la vostra piattaforma: OS, compilatore, versione gprof ecc –

+2

Ho trovato questo articolo: forse è di qualche utilità: http://unix.derkeiler.com/Newsgroups/comp.unix .programmer/2004-03/0938.html – LoudNPossiblyWrong

+0

Hai provato a utilizzare valgrind/kcachegrind per il profilo? Lo preferisco a gprof. –

risposta

5

Il codice presa deve gestire sistema interrotto chiamate indipendentemente dal profiler, ma sotto profiler è inevitabile. Questo significa avere il codice come.

if (errno == EINTR) { ... 

dopo ogni chiamata di sistema.

Dai uno sguardo, ad esempio, allo here per lo sfondo.

+0

Grande, grazie. Seguito: http://stackoverflow.com/questions/2958114/handling-eintr-with-goto –

1

gprof (here's the paper) è affidabile, ma only was ever intended to measure changes, e anche per questo, misura soltanto questioni CPU-bound. Non è mai stato pubblicizzato come utile per individuare i problemi . Questa è un'idea che altre persone hanno sovrapposto su di essa.

Considerare this method.

Un'altra buona opzione, se non ti dispiace spendere un po 'di soldi, è Zoom.

Aggiunto: Se posso solo darvi un esempio. Supponiamo che tu abbia una gerarchia di chiamata dove Main chiama un certo numero di volte, A chiama B un certo numero di volte, B chiama C un certo numero di volte, e C aspetta un I/O con un socket o un file, ed è praticamente tutto il programma fa. Ora, supponiamo inoltre che il numero di volte in cui ogni routine chiama il prossimo in basso è il 25% più volte di quanto realmente necessario. Poiché 1,25^3 è circa 2, significa che l'intero programma impiega il doppio del tempo necessario per l'esecuzione.

In primo luogo, poiché tutto il tempo è trascorso in attesa di I/O gprof non dirà nulla su come viene speso quel tempo, perché guarda solo il tempo "in esecuzione".

In secondo luogo, supporre (solo per argomento) è ha fatto contare il tempo di I/O. Potrebbe darti un grafico delle chiamate, in pratica dicendo che ogni routine prende il 100% delle volte. Che cosa vi dice? Niente di più di quello che sai già.

Tuttavia, se si prende un piccolo numero di campioni di stack, si vedrà su ognuno di essi le linee di codice in cui ogni routine chiama il successivo. In altre parole, non si tratta solo di fornire una stima del tempo approssimativo, è che ti indirizza a specifiche linee di codice che sono costose. Puoi guardare ogni riga di codice e chiedere se c'è un modo per farlo meno volte. Supponendo che lo facciate, otterrete il fattore 2 di accelerazione.

Le persone ottengono grandi fattori in questo modo. Nella mia esperienza, il numero di livelli di chiamata può essere facilmente di 30 o più. Ogni chiamata sembra necessaria, finché non chiedi se può essere evitata. Anche un piccolo numero di chiamate evitabili può avere un effetto enorme su molti livelli.