Nell'ingegneria del software, la profilazione ("profiling del programma", "profiling del software") è una forma di analisi dinamica del programma che misura, ad esempio, lo spazio (memoria) o la complessità temporale di un programma, l'uso di istruzioni particolari o la frequenza e la durata delle chiamate delle funzioni. Più comunemente, le informazioni derivanti dalla profilazione servono a supportare l'ottimizzazione di un software, indicando le parti più lente o pesanti su cui conviene lavorare.

La profilazione si ottiene modificando (strumentazione) il codice sorgente del programma o la sua forma eseguibile binaria usando uno strumento chiamato profiler (o profiler del codice) per poter rilevare il suo stato interno. I profilatori possono utilizzare una serie di tecniche diverse, come metodi basati su eventi, statistici, strumentati e di simulazione.

Raccolta degli eventi del programma I profilatori utilizzano una vasta gamma di tecniche per raccogliere dati, inclusi interrupt di processo, strumentazione del codice, simulazione delle istruzioni, hook del sistema operativo e contatori delle prestazioni. I profili risultanti sono utilizzati nel processo di ingegneria delle prestazioni per permettere allo sviluppatore e agli strumenti predisposti di effettuare modifiche mirate.

Uso dei profiler

L'output di un profiler può essere:

Un riepilogo statistico degli eventi osservati (un profilo)

Le informazioni di riepilogo del profilo vengono spesso visualizzate come annotazioni rispetto alle istruzioni del codice sorgente in cui si verificano gli eventi, quindi la dimensione dei dati prodotti dalla misurazione è proporzionale alla dimensione del codice del programma.

/ * ------------ sorgente ------------------- conteggio 0001 IF X = "A" 0055 0002 THEN DO 0003 ADD 1 to XCOUNT 0032 0004 ELSE 0005 IF X = "B" 0055

Un flusso di eventi registrati (una traccia)

Per i programmi sequenziali, di solito è sufficiente un profilo di riepilogo, ma i problemi di prestazioni nei programmi paralleli (l'attesa di messaggi o i problemi di sincronizzazione) dipendono spesso dalla relazione temporale degli eventi, richiedendo quindi una traccia completa delle diverse componenti per comprendere cosa sta succedendo e come queste interagiscono tra loro. La dimensione di una traccia (completa) è proporzionale rispetto alla lunghezza del percorso di istruzione del programma, rendendola poco pratica. Una traccia può quindi essere avviata in un punto di un programma e terminata in un altro punto per limitare l'output.

Un'interazione con l'hypervisor (monitoraggio continuo o periodico tramite visualizzazione sullo schermo, ad esempio)

Questo offre l'opportunità di attivare o disattivare manualmente una traccia in qualsiasi punto desiderato durante l'esecuzione, oltre a visualizzare le metriche in corso sul programma (ancora in esecuzione). Offre inoltre l'opportunità di sospendere i processi asincroni in punti critici per esaminare le interazioni con altri processi paralleli in modo più dettagliato.

Un profiler può essere applicato a un singolo metodo o a un intero modulo o a un programma, per identificare i colli di bottiglia delle prestazioni evidenziando il codice di che consuma più tempo. Un profiler può essere utilizzato per comprendere il codice da un punto di vista temporale, con l'obiettivo di ottimizzarlo per gestire diverse condizioni di runtime o vari carichi di lavoro. I risultati della profilazione possono essere sfruttati da un compilatore che fornisce l'ottimizzazione guidata dal profilo, ossia modifica il codice generato sulla base delle statistiche dell'esecuzione. I risultati della profilazione possono anche essere utilizzati per guidare la progettazione e l'ottimizzazione di un singolo algoritmo.

I profiler sono integrati in alcuni sistemi di gestione delle prestazioni delle applicazioni che aggregano i dati di profilazione per fornire informazioni sui carichi di lavoro delle transazioni nelle applicazioni distribuite, per esempio i database o servizi web.

Storia Gli strumenti di analisi delle prestazioni erano disponibili già sulle piattaforme IBM / 360 e IBM / 370 dai primi anni '70, generalmente basati su interruzioni del timer che registravano l'istruzione corrente a intervalli di timer impostati per rilevare "punti critici" nell'esecuzione del codice. Questo è stato un primo esempio di campionamento (vedi sotto). All'inizio del 1974 i simulatori di set di istruzioni permettevano un tracciamento completo e altre funzionalità di monitoraggio delle prestazioni.

L'analisi del programma basata su profiler in Unix risale al 1973, quando i sistemi Unix inclusero uno strumento di base, prof, che elencava ciascuna funzione e il tempo consumato per eseguirla. Nel 1982 gprof estese il concetto a un'analisi completa del grafico delle chiamate.S.L. Graham, P.B. Kessler, and M.K. McKusick, gprof: a Call Graph Execution Profiler, Proceedings of the SIGPLAN '82 Symposium on Compiler Construction, SIGPLAN Notices, Vol. 17, No 6, pp. 120-126; doi:10.1145/800230.806987

Nel 1994, Amitabh Srivastava e Alan Eustace della Digital Equipment Corporation hanno pubblicato un documento che descrive ATOMA. Srivastava and A. Eustace, ATOM: A system for building customized program analysis tools, Proceedings of the ACM SIGPLAN Conference on Programming language design and implementation (PLDI '94), pp. 196-205, 1994; ACM SIGPLAN Notices - Best of PLDI 1979-1999 Homepage archive, Vol. 39, No. 4, pp. 528-539; doi:10.1145/989393.989446 (Analysis Tools with OM, Strumenti di analisi con OM). La piattaforma ATOM converte un programma nel proprio profiler: in fase di compilazione, inserisce del codice aggiuntivo nel programma da analizzare. Questo codice aggiuntivo produce dati per la successiva analisi. Questa tecnica, che modifica un programma per analizzare sé stesso, è nota come " strumentazione ".

Nel 2004 i paper originali su gprof e ATOM sono comparsi nell'elenco dei 50 documenti PLDI più influenti per il ventennio nel 1979-1999.20 Years of PLDI (1979–1999): A Selection, Kathryn S. McKinley, Editor

Tipi di profiler basati sull'output

Flat profiler I flat profiler calcolano i tempi medi di chiamata, a partire dalle informazioni sulle chiamate stesse, e non suddividono i tempi di chiamata in base al chiamante o al contesto.

Profiler basato su grafo delle chiamate I profiler basati su grafo mostrano i tempi e le frequenze delle chiamate e le catene di chiamate coinvolte in base al chiamante. In alcuni strumenti non viene preservato il contesto completo.

Profiler sensibile agli input I profiler sensibili all'inputE. Coppa, C. Demetrescu, and I. Finocchi, Input-Sensitive Profiling, IEEE Trans. Software Eng. 40(12): 1185-1205 (2014); doi:10.1109/TSE.2014.2339825D. Zaparanuks and M. Hauswirth, Algorithmic Profiling, Proceedings of the 33rd ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2012), ACM SIGPLAN Notices, Vol. 47, No. 6, pp. 67-76, 2012; doi:10.1145/2254064.2254074T. Kustner, J. Weidendorfer, and T. Weinzierl, Argument Controlled Profiling, Proceedings of Euro-Par 2009 – Parallel Processing Workshops, Lecture Notes in Computer Science, Vol. 6043, pp. 177-184, 2010; doi:10.1007/978-3-642-14122-5 22 aggiungono un'ulteriore dimensione ai profiler flat o basati sul grafo delle chiamate e mettendo in relazione le misure delle prestazioni con le caratteristiche dei carichi di lavoro di input, come le dimensioni di input o i valori di input. Generano grafici che caratterizzano il modo in cui le prestazioni di un'applicazione variano in funzione del suo input.

Granularità dei dati nei tipi di profiler I profiler, che sono essi stessi programmi, analizzano i programmi target raccogliendo informazioni sulla loro esecuzione. In base alla granularità dei dati raccolti sono classificati in profiler basati su eventi o statistici. I profiler interrompono l'esecuzione del programma per raccogliere informazioni, il che limita la risoluzione degli eventi misurati tempo (eventi troppo veloci e rari possono essere ignorati), riducendo l'accuratezza. I profilatori a blocchi base riportano le quantità di cicli di clock della macchina dedicati all'esecuzione di ciascuna riga di codice o un tempo basato sulla loro somma; i tempi riportati per blocco di base potrebbero non riflettere una differenza tra utilizzo o meno della cache.

Profiler basati su eventi I linguaggi di programmazione elencati qui hanno profiler basati su eventi: Java: l'API JVMTI (JVM Tools Interface), precedentemente JVMPI (JVM Profiling Interface), fornisce hook ai profiler per intercettare eventi come chiamate, class-load, unload o entrata e uscita dai thread. .NET: È possibile collegare un agente di profilazione come server COM al CLR utilizzando lAPI di profilazione. Come Java, il runtime fornisce quindi vari callback nell'agente, per la rilevazione di eventi come l'utilizzo di JIT / enter / leave, la creazione di oggetti, ecc. È particolarmente potente in quanto l'agente di profilazione può riscrivere il bytecode dell'applicazione di destinazione in modi arbitrari. Python: la profilazione Python include il modulo profile, hotshot (basato sui grafi) e l'utilizzo della funzione 'sys.setprofile' per intercettare eventi come c_ {call, return, exception}, python_ {call, return, exception}. Librerie di terze parti forniscono ulteriori dettagli e permettono di esaminare programmi paralleli Ruby: Anche Ruby utilizza un'interfaccia simile a Python per la profilazione. Sono presenti flat-profiler in profile.rb, modulie e l'estensione C ruby-prof.

Profiler statistici Alcuni profilatori operano usando un campionamento. Un profiler di campionamento analizza lo stack di chiamate del programma target a intervalli regolari utilizzando gli interrupt di sistema operativo. I profili di campionamento sono in genere meno precisi e specifici dal punto di vista numerico, ma consentono al programma target di essere eseguito a velocità paragonabili a quella originale.

I dati risultanti non sono esatti, ma un'approssimazione statistica. "La quantità effettiva di errore è generalmente superiore a un periodo di campionamento. Infatti, se un valore è n volte il periodo di campionamento, l'errore previsto è la radice quadrata di n periodi di campionamento."

In pratica, i profiler basati sul campionamento possono spesso fornire un quadro più accurato dell'esecuzione del programma target rispetto ad altri approcci, in quanto non sono così invasivi rispetto al programma target e quindi non hanno così tanti effetti collaterali (come sulla memoria cache o sulle pipeline di decodifica delle istruzioni). Inoltre, poiché non influiscono molto sulla velocità di esecuzione, possono rilevare problemi che altrimenti rimarrebbero nascosti. Sono anche relativamente immuni dalla sopravvalutazione del costo di piccole routine chiamate spesso o cicli "stretti". Possono mostrare la quantità di tempo trascorso in modalità utente rispetto a quello trascorso in modalità kernel per l'elaborazione delle chiamate di sistema.

Tuttavia, il codice del kernel per gestire gli interrupt comporta una minore perdita di cicli della CPU, altera l'utilizzo della cache e non è in grado di distinguere le varie attività che si verificano nel codice del kernel ininterrotto (attività nell'ordine di microsecondi).

L'hardware dedicato può fare di più oltre: ARM Cortex-M3 e alcuni recenti processori MIPS con interfaccia JTAG hanno un registro chiamato PCSAMPLE, che campiona il contatore del programma in un modo davvero trasparente (poiché fatto da circuiti dedicati che non influenzano l'esecuzione normale) consentendo la raccolta non intrusiva di un profilo piatto.