Sfruttare IDisposable per realizzare un misuratore di tempistiche di esecuzione (Parte 1)

Sicuramente almeno una volta nella vostra carriera di sviluppatori vi sarà capitato di dover misurare la durata di esecuzione di un'istruzione oppure di un gruppo di istruzioni. La cosa più semplice da fare è dichiarare due variabili di tipo "DateTime", dove saranno registrate la data di inizio dell'operazione, e la data di fine; quindi eseguire una banale "end.Subtract(start)" per ottenere il "TimeSpan" che rappresenta l'effettiva misurazione della durata.

Non vi ho detto niente di nuovo, quindi. Ma ammettiamo che dobbiate misurare diverse porzioni e funzioni del vostro sistema. Se poi si tratta di un sistema che processa "batch" un quantitativo di dati considerevole, la cosa è un tantino dispersiva, e si rischia di sporcare tutto il codice con variabili come quelle sopra citate.

La domanda che mi sono posto è la seguente: ho modo di ottenere il medesimo risultato evitando di inquinare il mio codice con vagonate di istruzioni che hanno il solo scopo di verificare le performance applicative, ma nessun significato a livello di flusso funzionale?

La prima risposta che mi sono dato è : "No, non è possibile eliminare del tutto il codice di misurazione.". E, a pensarci bene, è comprensibile che alcuni "marker" debbano necessariamente essere incorporati nel codice per permettere di identificare il punto di inizio e quello di fine della misurazione. Esistono alcuni strumenti come "PostSharp" che eseguono una ricompilazione del nostro sorgente inserendo altro codice prima di compilare il tutto in "IL", ma non è questo lo scopo di questo post (anche se ritengo PostSharp uno strumento estremamente valido).

Prima di buttarmi a capofitto nella questione, ho "scomposto" il problema: avevo bisogno di una rilevazione temporale prima dell'istruzione da misurare, e una dopo l'esecuzione di quest'ultima. Al termine della rilevazione, per semplicità di spiegazione, diciamo che vogliamo stampare sulla console il tempo di esecuzione corredato di un messaggio che ci permetta di identificare facilmente "cosa abbiamo misurato".

Ammettiamo quindi di voler ottenere un'uscita del tipo:
"13/03/2013 12:32:23 - 'Estrazione prodotti' (START)",
"13/03/2013 12:36:25 - 'Estrazione prodotti' (END -> Duration 00:04:02)"
rispettivamente per l'inizio della misurazione e al completamento di questa ipotetica estrazione di prodotti da una base dati.

Quindi ho un inizio e ho una fine...Perchè non usare l'interfaccia "IDisposable" per realizzare qualche cosa cosa di sintetico ed efficace? L'utilizzo di quello che andremo a realizzare è presentato qui sotto: una semplice dichiarazione di "using" sull'helper statico "Tracer" (specificando il messaggio) e il gioco è fatto. Per fare tutto ciò, come detto, è necessario che la chiamata al metodo "Duration" emetta un oggetto che implementa l'interfaccia "IDisposable", che come sappiamo è facilmente utilizzabile con la clausola di "using": l'oggetto viene istanziato nella definizione, quindi rilasciato alla chiusura del "bracket" di competenza dello "using" stesso.

Volere vedere il contenuto di "Duration" e l'implementazione reale di "IDisposable"?
La prossima volta... ;)
M.

Commenti

Post popolari in questo blog

Restore di un database SQL Server in un container Docker

Cancellazione fisica vs cancellazione logica dei dati

WCF RESTful service: esposizione del servizio