Berechnen Sie die Ausführungszeit einer Methode

533

Mögliches Duplikat:
Wie messe ich, wie lange eine Funktion ausgeführt wird?

Ich habe eine E / A-Zeitmessmethode, mit der Daten von einem Ort an einen anderen kopiert werden. Was ist die beste und realistischste Methode zur Berechnung der Ausführungszeit? Thread? Timer? Stopwatch? Irgendeine andere Lösung? Ich möchte das genaueste und kürzeste so viel wie möglich.

Mahdi Tahsildari
quelle

Antworten:

1131

Stopwatch wurde für diesen Zweck entwickelt und ist eine der besten Möglichkeiten, die Zeitausführung in .NET zu messen.

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

Verwenden Sie DateTime nicht, um die Zeitausführung in .NET zu messen.


AKTUALISIEREN:

Wie von @ series0ne im Kommentarbereich hervorgehoben: Wenn Sie eine wirklich genaue Messung der Ausführung eines Codes wünschen, müssen Sie die im Betriebssystem integrierten Leistungsindikatoren verwenden. Die folgende Antwort enthält eine schöne Übersicht.

Darin Dimitrov
quelle
2
Genau, und was ist mit diesem Fall: Ich habe eine foreach-Schleife, die eine ThreadPool.QueueUserWorkItem(delegate { CopyFiles(folder, dest); }); Innenseite hat, aber die Stoppuhr stoppt, bevor alles erledigt ist.
Mahdi Tahsildari
13
@DarinDimitrov - Stoppuhr ist nicht ganz genau? Denken Sie daran, dass .NET-Hintergrundgeräusche (z. B. JITing) unterschiedliche Ausführungszeiten verursachen. Daher sollte das OP für genaue Messungen realistisch einen Leistungsprofiler verwenden.
Matthew Layton
3
@ series0ne, sehr guter Punkt. Ich werde meine Antwort aktualisieren, um Ihren wertvollen Kommentar aufzunehmen.
Darin Dimitrov
7
@DarinDimitrov, ich hatte kürzlich ein Interview mit einem sehr erfahrenen Senior-Entwickler. Er wies mich darauf hin, dass die Verwendung von DateTimes tatsächlich genauer ist als die Verwendung einer StopWatch. Er sagte, der Grund dafür sei, dass die Stoppuhr in .NET die CPU-Affinität nicht berücksichtigt. Wenn Ihr Thread von einem Kern zum anderen wechselt, berücksichtigt die Stoppuhr daher nicht die Ausführungszeit über die anderen Kerne hinweg. nur der, bei dem der Thread mit der Ausführung begann. Wie ist Ihre Meinung dazu?
Matthew Layton
2
@ series0ne, was der leitende Entwickler Ihnen über die Stoppuhr und DateTime erzählt hat, ist absolut wahr. Abgesehen davon, dass Sie mit DateTime nicht genügend Genauigkeit haben. Das Problem ist, dass es in .NET keine solche Klasse gibt, die Ihnen all diese Funktionen ermöglicht.
Darin Dimitrov
75

Aus persönlicher Erfahrung kann die System.Diagnostics.StopwatchKlasse verwendet werden, um die Ausführungszeit einer Methode zu messen. ACHTUNG : Sie ist nicht ganz genau!

Betrachten Sie das folgende Beispiel:

Stopwatch sw;

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

sw.Stop();

Beispielergebnisse

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

Jetzt wunderst du dich; "Nun, warum hat es das erste Mal 132 ms gedauert und den Rest der Zeit deutlich weniger?"

Die Antwort lautet, dass Stopwatch"Hintergrundgeräusche" in .NET wie JITing nicht kompensiert werden. Wenn Sie Ihre Methode zum ersten Mal ausführen, wird sie daher zuerst von .NET JIT ausgeführt. Die dafür erforderliche Zeit wird zur Ausführungszeit addiert. Ebenso führen andere Faktoren dazu, dass die Ausführungszeit variiert.

Was Sie wirklich auf der Suche nach absoluter Genauigkeit sein sollten, ist das Leistungsprofil !

Schauen Sie sich Folgendes an:

RedGate ANTS Performance Profiler ist ein kommerzielles Produkt, liefert jedoch sehr genaue Ergebnisse. - Steigern Sie die Leistung Ihrer Anwendungen mit .NET-Profilen

Hier ist ein StackOverflow-Artikel zur Profilerstellung: - Was sind einige gute .NET-Profiler?

Ich habe auch einen Artikel über Leistungsprofile mit Stoppuhr geschrieben, den Sie sich ansehen möchten - Leistungsprofile in .NET

Matthew Layton
quelle
2
@ Mahditahsildari Kein Problem. Froh, dass ich helfen konnte! :-)
Matthew Layton
41
Ich bin mir nicht sicher, warum dies ein Beispiel für Ungenauigkeit ist . Die Stoppuhr misst genau die Gesamtkosten des ersten Anrufs, was sicherlich für den Kunden relevant ist, der diesen Code ausführen wird. Es ist ihnen egal, ob diese 132 Millisekunden der Methodenausführung oder dem Jitter belastet werden, sie kümmern sich um die verstrichene Gesamtzeit.
Eric Lippert
2
@ series0ne Wenn Sie sich für die Leistung einer Schleife interessieren, messen Sie die Leistung einer Schleife. Sie nicht einfach davon ausgehen , dass etwas zu tun n mal Mittel wird es genau n - mal langsamer , wie es einmal ausgeführt wird .
Svick
3
Zunächst sollte das Codebeispiel die Ausgabe mit immer größerer Zahl erzeugen, da StopWatch in der Schleife niemals zurückgesetzt wird. Und mit "sollte" meine ich, dass es das tut (ich habe es überprüft). Ihre Ausgabe stimmt also nicht mit dem Code überein. Zweitens war die erste Messung dieselbe wie die andere, als ich den Code korrigierte, um ein Stop / Write / Reset / Start in der Schleife durchzuführen. Ich vermute, Ihr DoSomething macht beim ersten Start etwas länger. JIT kann der Grund dafür sein oder auch nicht, aber es ist nicht so, dass die Stoppuhr die Messung beeinflusst. Daher -1.
ILIA BROUDNO
2
ILIA BROUDNO ist absolut richtig, ich habe die gleichen Ergebnisse erzielt. @ series0ne, Sie haben eine Console.WriteLine in der Schleife, die die bisherige ms schreibt. Da Sie die Uhr erst nach dem Ende der Schleife anhalten, nimmt sie mit jeder Iteration mit der Zeit zu. Daher sollten wir etwa 3, 6, 10, 12, 15 ... sehen, wenn sich die Zeit über die Ausführungen ansammelt.
Rui Miguel Pinheiro
29

StopWatch Klasse sucht nach Ihrer besten Lösung.

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

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

Es hat auch ein statisches Feld namens Stopwatch.IsHighResolution. Dies ist natürlich ein Hardware- und Betriebssystemproblem.

Gibt an, ob der Timer auf einem hochauflösenden Leistungsindikator basiert.

Soner Gönül
quelle
18

Wenn Sie die Leistung verstehen möchten, verwenden Sie am besten einen Profiler.

Andernfalls bietet System.Diagnostics.StopWatch einen hochauflösenden Timer.

Jeff Foster
quelle
Absolut korrekt! Ich bin ein wenig entmutigt, dass so viele hier vorgeschlagen haben, die Stoppuhr zu verwenden, da sie nicht ganz genau ist. Wie Sie jedoch vorgeschlagen haben, einen Leistungsprofiler zu verwenden, ist dies der richtige Weg! +1
Matthew Layton
7

StopWatch verwendet den hochauflösenden Zähler

Die Stoppuhr misst die verstrichene Zeit durch Zählen der Timer-Ticks im zugrunde liegenden Timer-Mechanismus. Wenn die installierte Hardware und das installierte Betriebssystem einen hochauflösenden Leistungsindikator unterstützen, verwendet die Stoppuhrklasse diesen Zähler, um die verstrichene Zeit zu messen. Andernfalls verwendet die Stoppuhrklasse den Systemzeitgeber, um die verstrichene Zeit zu messen. Verwenden Sie die Felder Frequenz und IsHighResolution, um die Genauigkeit und Auflösung der Stoppuhr-Timing-Implementierung zu bestimmen.

Wenn Sie IO messen, werden Ihre Zahlen wahrscheinlich von externen Ereignissen beeinflusst, und ich würde mir so viele Sorgen machen. Genauigkeit (wie oben angegeben). Stattdessen würde ich eine Reihe von Messungen durchführen und den Mittelwert und die Verteilung dieser Zahlen berücksichtigen.

Brian Agnew
quelle
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);
   }
 }
Md.Rakibuz Sultan
quelle