Calcola il tempo di esecuzione di un metodo


533

Possibile duplicato:
come misurare la durata di una funzione?

Ho un metodo I / O che richiede tempo che copia i dati da una posizione a un'altra. Qual è il modo migliore e più reale per calcolare i tempi di esecuzione? Thread? Timer? Stopwatch? Qualche altra soluzione? Voglio quello più esatto e il più breve possibile.

Risposte:


1131

Stopwatch è progettato per questo scopo ed è uno dei modi migliori per misurare l'esecuzione del tempo in .NET.

var watch = System.Diagnostics.Stopwatch.StartNew();
// the code that you want to measure comes here
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;

Non utilizzare DateTime per misurare l'esecuzione del tempo in .NET.


AGGIORNARE:

Come sottolineato da @ series0ne nella sezione commenti: se si desidera una misurazione davvero precisa dell'esecuzione di un codice, è necessario utilizzare i contatori delle prestazioni integrati nel sistema operativo. La seguente risposta contiene una bella panoramica.


2
Esatto, e che dire di questo caso: ho un ciclo foreach che ha un ThreadPool.QueueUserWorkItem(delegate { CopyFiles(folder, dest); }); interno, ma il cronometro si ferma prima che tutto sia fatto.
Mahdi Tahsildari,

13
@DarinDimitrov - Il cronometro non è del tutto preciso? ricordare che il rumore di sottofondo .NET (come JITing) provoca tempi di esecuzione variabili. Pertanto, realisticamente, per misurazioni accurate, l'OP dovrebbe utilizzare un profiler delle prestazioni.
Matthew Layton,

3
@ series0ne, ottimo punto. Aggiornerò la mia risposta per includere il tuo prezioso commento.
Darin Dimitrov,

7
@DarinDimitrov, recentemente ho avuto un'intervista con uno sviluppatore senior molto abile. Mi ha fatto notare che l'utilizzo di DateTimes è in realtà più accurato rispetto all'utilizzo di uno StopWatch. Ha detto che la ragione di ciò è che il cronometro in .NET non tiene conto dell'affinità della CPU, e quindi, se il thread si sposta da un core all'altro, StopWatch non tiene conto del tempo di esecuzione attraverso gli altri core; solo quello in cui il thread ha iniziato l'esecuzione. Qual è la tua opinione su questo?
Matthew Layton,

2
@ series0ne, ciò che lo sviluppatore senior ti ha detto del cronometro e del DateTime è assolutamente vero. Tranne che con DateTime non hai abbastanza precisione. Il problema è che non esiste una classe del genere in .NET che ti consentirebbe tutte quelle funzionalità.
Darin Dimitrov,

75

Per esperienza personale, la System.Diagnostics.Stopwatchclasse può essere utilizzata per misurare i tempi di esecuzione di un metodo, tuttavia, ATTENZIONE : non è del tutto esatto!

Considera il seguente esempio:

Stopwatch sw;

for(int index = 0; index < 10; index++)
{
    sw = Stopwatch.StartNew();
    DoSomething();
    Console.WriteLine(sw.ElapsedMilliseconds);
}

sw.Stop();

Risultati di esempio

132ms
4ms
3ms
3ms
2ms
3ms
34ms
2ms
1ms
1ms

Ora ti stai chiedendo; "beh, perché ci sono voluti 132ms la prima volta e significativamente meno il resto del tempo?"

La risposta è che Stopwatchnon compensa l'attività di "rumore di fondo" in .NET, come JITing. Pertanto, la prima volta che si esegue il metodo, .NET JIT è il primo. Il tempo necessario per farlo viene aggiunto al tempo dell'esecuzione. Allo stesso modo, anche altri fattori possono variare i tempi di esecuzione.

Quello che dovresti davvero cercare con assoluta precisione è Performance Profiling !

Dai un'occhiata a quanto segue:

RedGate ANTS Performance Profiler è un prodotto commerciale, ma produce risultati molto precisi. - Aumenta le prestazioni delle tue applicazioni con il profilo .NET

Ecco un articolo StackOverflow sulla profilazione: - Quali sono alcuni buoni profilatori .NET?

Ho anche scritto un articolo sulla profilazione delle prestazioni usando il cronometro che potresti voler guardare - Profili delle prestazioni in .NET


2
@mahditahsildari Nessun problema. Sono contento di poterti aiutare! :-)
Matthew Layton,

41
Non sono sicuro del perché questo sia un esempio di inesattezza . Il cronometro sta misurando accuratamente il costo totale della prima chiamata, che è sicuramente ciò che è rilevante per il cliente che eseguirà questo codice. A loro non importa se quei 132 millisecondi sono addebitati all'esecuzione del metodo o al jitter, si preoccupano del tempo totale trascorso.
Eric Lippert,

2
@ series0ne Se ti preoccupi delle prestazioni di un loop, allora misura le prestazioni di un loop. Non dare semplicemente per scontato che fare qualcosa n volte significa che sarà esattamente n volte più lento di eseguirlo una volta.
svick,

3
Prima di tutto, l'esempio di codice dovrebbe produrre l'output con un numero sempre crescente poiché StopWatch non viene mai ripristinato nel loop. E per "dovrei" intendo dire che (ho controllato). Quindi il tuo output non corrisponde al codice. In secondo luogo, quando ho corretto il codice per eseguire un arresto / scrittura / ripristino / avvio nel ciclo, la prima misurazione era la stessa del resto. Suppongo che il tuo DoSomething faccia qualcosa più a lungo la prima volta che viene eseguito. La ragione potrebbe essere o meno la ragione, ma non è che il cronometro influenzi la misurazione. Quindi -1.
ILIA BROUDNO,

2
ILIA BROUDNO ha assolutamente ragione, ho ottenuto gli stessi risultati. @ series0ne, hai una Console.WriteLine all'interno del ciclo, scrivendo finora il ms; perché fermi l'orologio DOPO che il ciclo termina, aumenta con il passare del tempo ad ogni iterazione, quindi dovremmo vedere qualcosa come 3, 6, 10, 12, 15 ... mentre il tempo si accumula durante le esecuzioni.
Rui Miguel Pinheiro,

29

StopWatch class cerca la tua migliore soluzione.

Stopwatch sw = Stopwatch.StartNew();
DoSomeWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

Inoltre ha un campo statico chiamato Stopwatch.IsHighResolution. Naturalmente, si tratta di un problema hardware e di sistema operativo.

Indica se il timer si basa su un contatore delle prestazioni ad alta risoluzione.


18

Se sei interessato a capire le prestazioni, la risposta migliore è usare un profiler.

Altrimenti, System.Diagnostics.StopWatch fornisce un timer ad alta risoluzione.


Assolutamente corretto! Sono un po 'scoraggiato dal fatto che così tanti qui abbiano suggerito di usare il cronometro, poiché non è del tutto esatto. Tuttavia, come hai suggerito di utilizzare un profiler di Performance, questo è il modo corretto di farlo! +1
Matthew Layton,

7

StopWatch utilizzerà il contatore ad alta risoluzione

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

Se stai misurando IO, le tue figure saranno probabilmente influenzate da eventi esterni, e mi preoccuperei così tanto. esattezza (come indicato sopra). Invece prenderei una serie di misurazioni e considererei la media e la distribuzione di quelle cifre.


0
 using System.Diagnostics;
 class Program
 {
    static void Test1()
    {
        for (int i = 1; i <= 100; i++)
        {
            Console.WriteLine("Test1 " + i);
        }
    }
  static void Main(string[] args)
    {

        Stopwatch sw = new Stopwatch();
        sw.Start();
        Test1();
        sw.Stop();
        Console.WriteLine("Time Taken-->{0}",sw.ElapsedMilliseconds);
   }
 }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.