Domanda

Voglio misurare l'esecuzione di un pezzo di codice e mi chiedo che cosa è il metodo migliore per fare questo?

Opzione 1:

DateTime StartTime = DateTime.Now;

//Code

TimeSpan ts = DateTime.Now.Subtract(StartTime);
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");

Opzione 2:utilizzando Sistema.La diagnostica;

    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    //Code

    stopWatch.Stop();
    // Get the elapsed time as a TimeSpan value.
    TimeSpan ts = stopWatch.Elapsed;

    // Format and display the TimeSpan value.
    string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
    Console.WriteLine(elapsedTime, "RunTime");

Questo non è semplicemente per il benchmarking, in realtà fa parte dell'applicazione.La volta che la funzione richiede per l'esecuzione pertinenti dati.Non ha tuttavia bisogno di essere atomica o precisi.

Quale opzione è meglio per il codice di produzione, o c'è qualcun altro di utilizzare qualcosa di diverso e forse migliore?

È stato utile?

Soluzione

La classe Stopwatch è specificamente progettato per misurare il tempo trascorso e può (se disponibile sul proprio hardware) fornire una buona granularità / precisione utilizzando un timer sottostante hardware ad alta frequenza. Quindi questo sembra la scelta migliore.

Il IsHighResolution proprietà può essere utilizzato per determinare se temporizzazione ad alta risoluzione è disponibile. Per la documentazione, questo offre un wrapper di classe sul 'migliore disponibile' API Win32 per la temporizzazione precisa:

  

In particolare, il campo Frequency e   Metodo GetTimestamp può essere utilizzato in   posto del non gestito Win32 API   QueryPerformanceFrequency e   QueryPerformanceCounter.

Non c'è sfondo dettagliate su quelli Win32 API [qui] e nella documentazione MSDN legate 2 .

  

ad alta risoluzione del timer

     

Un contatore è un termine generico usato in   programmazione per fare riferimento a un   incremento variabile. alcuni sistemi   includere una performance ad alta risoluzione   contatore che fornisce ad alta risoluzione   trascorsi i tempi.

     

Se una performance ad alta risoluzione   contatore esiste sul sistema, è possibile   utilizzare il QueryPerformanceFrequency   funzione di esprimere la frequenza, in   conteggi per secondo. Il valore della   conteggio è processore dipendente. su alcuni   processori, per esempio, il conteggio   potrebbe essere il tasso di ciclo del   di clock del processore.

     

QueryPerformanceCounter Funzione   recupera il valore corrente della   alta risoluzione contatore di prestazioni.   Chiamando questa funzione al   inizio e fine di una sezione di   codice, un'applicazione utilizza essenzialmente   il contatore come ad alta risoluzione   Timer. Per esempio, supponiamo che    QueryPerformanceFrequency indica   che la frequenza del   contatore di prestazioni ad alta risoluzione è   50.000 conteggi per secondo. Se la   le chiamate di applicazione    QueryPerformanceCounter immediatamente   prima e subito dopo la   sezione di codice sia programmata, la   i valori del contatore potrebbero essere 1500 conta   e 3500 conteggi, rispettivamente. Questi   valori indicherebbero che .04 secondi   (2000 conteggi) trascorso mentre il codice   eseguito.

Altri suggerimenti

Non è solo che StopWatch è più preciso, ma anche che DateTime.Now darà risultati non corretti in alcune circostanze.

Considerare ciò che accade durante l'ora legale switch-over, per esempio utilizzando DateTime.Now può effettivamente dare un negativo la risposta!

Io in genere uso StopWatch per questo tipo di situazione.

Da pagina MSDN :

  

Cronometro

     

Fornisce un insieme di metodi e   le proprietà che è possibile utilizzare per   misurare con precisione il tempo trascorso.

Nel seguente post Io lo uso per confrontare il tempo di esecuzione di LINQ vs PLINQ:

Parallel LINQ (PLINQ) con Visual Studio 2010

Né farà male le prestazioni, perché si dice che non è così critica. StopWatch sembra più appropriato - si sta solo il tempo di tanto e non uno da un altro data sottrarre. Data roba prende un po 'più di memoria e CPU tempo per affrontare. Ci sono anche modi per rendere il codice più pulito, nel caso in cui si prevede di riutilizzare in più punti. Il sovraccarico using viene in mente. Cercherò un esempio. Ok, il codice rubato da:

http://stevesmithblog.com/blog/great -Utilizza-di-uso-dichiarazione-in-c /

public class ConsoleAutoStopWatch : IDisposable
{
    private readonly Stopwatch _stopWatch;

    public ConsoleAutoStopWatch()
    {
        _stopWatch = new Stopwatch();
        _stopWatch.Start();
    }

    public void Dispose()
    {
        _stopWatch.Stop();
        TimeSpan ts = _stopWatch.Elapsed;

        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                                           ts.Hours, ts.Minutes, ts.Seconds,
                                           ts.Milliseconds / 10);
        Console.WriteLine(elapsedTime, "RunTime");
    }
}

private static void UsingStopWatchUsage()
{
    Console.WriteLine("ConsoleAutoStopWatch Used: ");
    using (new ConsoleAutoStopWatch())
    {
        Thread.Sleep(3000);
    }
}

Entrambi saranno probabilmente soddisfare le vostre esigenze più che bene, ma direi uso StopWatch. Perché? Causa è significato per l'attività che si sta facendo.

Hai una classe che è costruito per restituire la data / ora corrente, che, come accade può essere utilizzato per le cose temporali, e hai una classe specificamente progettato per le cose temporali.

In questo caso le differenze esistono veramente solo se avete bisogno di precisione millisecondo (nel qual caso StopWatch è più preciso), ma come un principio generale, se uno strumento esiste specificamente per l'attività che stai cercando allora è il migliore per uso.

Ho un po 'di classe per fare questo genere di cose ad hoc. Esso utilizza la classe cronometro - c # micro perfomance test .

ad es.

var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));

L'uso di sotto codice

DateTime dExecutionTime;
dExecutionTime = DateTime.Now;
      TimeSpan span = DateTime.Now.Subtract(dExecutionTime);
                  lblExecutinTime.Text = "total time taken " +   Math.Round(span.TotalMinutes,2) + " minutes .   >>---> " + DateTime.Now.ToShortTimeString();

Ho preso la risposta di Hamish semplificato e reso un po 'più generale nel caso in cui devi effettuare il login da qualche altra parte:

public class AutoStopWatch : Stopwatch, IDisposable {

    public AutoStopWatch() {
        Start();
    }

    public virtual void Dispose() {
        Stop();
    }
}

 public class AutoStopWatchConsole : AutoStopWatch {

    private readonly string prefix;

    public AutoStopWatchConsole(string prefix = "") {
        this.prefix = prefix;
    }

    public override void Dispose() {
        base.Dispose();

        string format = Elapsed.Days > 0 ? "{0} days " : "";
        format += "{1:00}:{2:00}:{3:00}.{4:00}";

        Console.WriteLine(prefix + " " + format.Format(Elapsed.Days, Elapsed.Hours, Elapsed.Minutes, Elapsed.Seconds, Elapsed.Milliseconds / 10));
    }
}

private static void Usage() {

    Console.WriteLine("AutoStopWatch Used: ");
    using (var sw = new AutoStopWatch()) {
        Thread.Sleep(3000);

        Console.WriteLine(sw.Elapsed.ToString("h'h 'm'm 's's'"));
    }

    Console.WriteLine("AutoStopWatchConsole Used: ");
    using (var sw = new AutoStopWatchConsole()) {
        Thread.Sleep(3000);
    }

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