2010-05-27 14 views
79

Volevo monitorare le prestazioni del mio codice in modo da memorizzare l'ora di inizio e di fine utilizzando System.DateTime.Now. Ho preso la differenza tra i due come il tempo di esecuzione del mio codice.Cronometro rispetto all'utilizzo di System.DateTime.Now per eventi di temporizzazione

Ho notato che la differenza non sembrava accurata. Così ho provato a utilizzare un oggetto Stopwatch. Questo si è rivelato molto, molto più accurato.

Qualcuno può dirmi perché Stopwatch sarebbe più preciso del calcolo della differenza tra ora di inizio e di fine utilizzando System.DateTime.Now?

BTW, non sto parlando di un decimo di percentuale. Ottengo una differenza del 15-20%.

+2

Sulla base del tuo commento alla risposta di Kelsey, sarei interessato a vedere il codice che registra gli orari di inizio e fine. Una differenza di 11 secondi (enorme) non ha nulla a che fare con le differenze di accuratezza delle due classi, quindi qualcos'altro deve andare avanti. –

+3

Inoltre, se ti interessa solo il 'TimeSpan' tra due date, di solito è meglio usare' DateTime.UtcNow' invece di 'DateTime.Now', dato che di solito non vuoi i turni diurni e l'ora locale variazioni per influenzare il risultato. –

+0

@DanielPryden, vedere [The Case Against DateTime.Now] (http://codeofmatt.com/2013/04/25/the-case-against-datetime-now/), che rende esattamente questo punto. +1 –

risposta

65

Secondo MSDN:

Il cronometro misura il tempo trascorso contando timer zecche nel meccanismo temporizzatore sottostante. Se l'hardware e il sistema operativo installati supportano un contatore di prestazioni ad alta risoluzione, la classe Cronometro utilizza quel contatore per misurare il tempo trascorso. In caso contrario, la classe Cronometro utilizza il timer di sistema per misurare il tempo trascorso. Utilizzare i campi Frequency e IsHighResolution per determinare la precisione e la risoluzione dell'implementazione del cronometro.

Utilizza una risoluzione/precisione superiore a DateTime.Now.

È anche possibile controllare questi link correlati:

Environment.TickCount vs DateTime.Now

Is DateTime.Now the best way to measure a function's performance?

DateTime è abbastanza buono per la precisione al secondo, probabilmente, ma al di là di tutto ciò che mi sento di raccomandare StopWatch.

6

questo timing function performance collegamento discute il problema esatto, in particolare questo paragrafo:

Il problema è che, secondo MSDN la risoluzione della funzione DateTime.Now è 10 + millisecondi, e abbiamo bisogno di chiamare due volte! In tal modo si introdurrebbe uno swing di 20+ ms nella misurazione del tempo di esecuzione. Dato che spesso le nostre chiamate di funzione sono molto più veloci da restituire rispetto a questa finestra da 20 ms, questo non è abbastanza buono.

MODIFICA: Suona come il secondo DateTime.Ora viene richiamato in un momento diverso rispetto a quando il metodo del cronometro termina.

26

E 'meglio utilizzare la classe cronometro perché è molto più preciso di sottrarre i valori DateTime:

Stopwatch s = Stopwatch.StartNew(); 
// Tested code here 
s.Stop(); 
Console.WriteLine("Elapsed Time: {0} ms", s.ElapsedMilliseconds); 

Purtroppo, questo semplice pezzo di codice non sarà sufficiente per ottenere misure accurate maggior parte delle volte perché non c'è un sacco di attività in corso sotto il cofano del sistema operativo, che può rubare un po 'di tempo di CPU e rallentare l'esecuzione del codice. Ecco perché è meglio eseguire i test più volte e quindi rimuovere i tempi più bassi e quelli più alti. Per quella puprose è una buona soluzione avere un metodo che esegue il codice testato più volte, rimuove i tempi minimi e massimi e calcola il tempo medio. Ho pubblicato uno sample testing method in my blog.

+0

Ho controllato il link del tuo blog. C'è un leggero errore nel calcolo del tempo medio. Invece di 'double averageTime = ((double) totalTime)/(count - discardCount);' dovrebbe essere 'double averageTime = ((double) totalTime)/(count - (2 * discardCount));'. No? – displayName

+0

Ciao, ** no non dovrebbe, il codice nel blog è corretto **. Si prega di dare un'occhiata alla linea, dove 'count' è definito. È definito come: 'int count = ripetizioni - discardCount;'. Questo è il motivo per cui nel calcolare il tempo medio sottrarre 'discardCount' solo una volta (è già stato sottratto una volta). Saluti. –

+0

Questo è corretto. Non ho prestato attenzione ad esso. Hai ragione. – displayName

Problemi correlati