Domanda

Alcune delle piattaforme su cui sviluppo non dispongono di strumenti di profilazione. Sto cercando suggerimenti / tecniche che hai usato personalmente per aiutarti a identificare gli hotspot, senza l'uso di un profiler.

La lingua di destinazione è C ++.

Sono interessato a ciò che hai usato personalmente.

È stato utile?

Soluzione

Ho trovato molto utile quanto segue:

#ifdef PROFILING
# define PROFILE_CALL(x) do{ \
    const DWORD t1 = timeGetTime(); \
    x; \
    const DWORD t2 = timeGetTime(); \
    std::cout << "Call to '" << #x << "' took " << (t2 - t1) << " ms.\n"; \
  }while(false)
#else
# define PROFILE_CALL(x) x
#endif

Quale può essere utilizzato nella funzione di chiamata in quanto tale:

PROFILE_CALL(renderSlow(world));
int r = 0;
PROFILE_CALL(r = readPacketSize());

Altri suggerimenti

Non è uno scherzo: oltre a scaricare i tempi per std :: cout e altri approcci orientati al testo / dati, uso anche la funzione Beep (). C'è qualcosa nel sentire il divario di silenzio tra due "Beep" punti di controllo che generano un diverso tipo di impressione.

È come la differenza tra guardare uno spartito scritto e UDIRE la musica. È come la differenza tra leggere rgb (255,0,0) e vedere il rosso dell'autopompa.

Quindi, in questo momento, ho un'app client / server e con segnali acustici di frequenze diverse, segnando dove il client invia il messaggio, dove il server inizia la sua risposta, termina la sua risposta, dove la risposta entra prima nel client, ecc. Posso naturalmente avere un'idea di dove il tempo è trascorso.

In sostanza, se uno strumento di profilazione non è disponibile, si emula ciò che un profiler avrebbe fatto. Inserisci i contatori nelle funzioni che ritieni interessanti e conti quante volte e potenzialmente con quale dimensione / tipo di argomenti vengono chiamati.

Se si ha accesso a qualsiasi timer sulla propria piattaforma, è possibile avviarli / arrestarli all'inizio / alla fine di tali funzioni per ottenere anche le informazioni sui tempi di esecuzione, se ciò non è chiaro dal codice. Questo ti darà il massimo vantaggio per il tuo buck in codice complesso, poiché di solito ci saranno troppe funzioni per strumentarle tutte. Invece, puoi ottenere il tempo speso in alcune sezioni di codice dedicando un timer a ciascuno di essi.

Queste due tecniche in tandem possono formare un approccio iterativo, in cui trovi un'ampia sezione di codice che consuma la maggior parte dei tuoi cicli usando i timer, quindi strumenti singole funzioni con una granularità più fine per approfondire il problema.

Se la durata è qualcosa di sufficientemente lungo (ad esempio un minuto o più), eseguo il software in un debugger, quindi interrompo alcune volte e vedo dove si interrompe il debugger, questo dà un'idea molto approssimativa di ciò che il software è attivo a (es. se ti rompi 10 volte e sono tutti nello stesso posto, questo ti dice qualcosa di interessante!). Molto grezzo e pronto ma non richiede strumenti, strumenti ecc.

Non sono sicuro delle piattaforme che avevi in ??mente, ma sui microcontrollori incorporati, a volte è utile modificare una linea di uscita digitale di riserva e misurare l'ampiezza dell'impulso usando un oscilloscopio, un contatore / timer o un analizzatore logico.

Vorrei usare la regola 80/20 e mettere i timer attorno a hotspot o percorsi di chiamata interessanti. Dovresti avere un'idea generale di dove saranno i colli di bottiglia (o almeno la maggior parte dei percorsi di esecuzione) e utilizzare il timer ad alta risoluzione dipendente dalla piattaforma appropriato (QueryPerformanceCounters, gettimeofday, ecc.).

Di solito non mi preoccupo di nulla all'avvio o allo spegnimento (a meno che non sia necessario) e avrò ben definiti "punti di strozzatura", di solito il passaggio di messaggi o una sorta di calcolo algoritmico. In genere ho scoperto che i messaggi sink / srcs (sink moreso), code, mutex e semplici mess-up (algoritmi, loop) di solito rappresentano la maggior parte della latenza in un percorso di esecuzione.

Stai usando Visual Studio?

È possibile utilizzare le opzioni / Gh e / GH. Ecco un esempio che riguarda l'ispezione dello stack

Questi flag ti permettono, per file per file, di registrare funzioni non decorate che vengono chiamate ogni volta che un metodo viene inserito e / o lasciato in fase di esecuzione.

È quindi possibile registrare tutte le volte delle informazioni di profilazione, non solo le informazioni di temporizzazione. Stack-dump, indirizzo chiamante, indirizzo di ritorno, ecc. Ciò è importante, perché potresti voler sapere che 'funzione X ha usato il tempo Y sotto la funzione Z' e non solo il tempo totale impiegato nella funzione X.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top