Ich muss einen Engpass finden und die Zeit so genau wie möglich messen.
Ist das folgende Codefragment der beste Weg, um die Leistung zu messen?
DateTime startTime = DateTime.Now;
// Some execution process
DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
Antworten:
Nein, ist es nicht. Benutze die Stoppuhr (in
System.Diagnostics
)Die Stoppuhr prüft automatisch, ob hochpräzise Timer vorhanden sind.
Es ist erwähnenswert, dass dies
DateTime.Now
oft etwas langsamer ist alsDateTime.UtcNow
aufgrund der Arbeit, die mit Zeitzonen, Sommerzeit und dergleichen erledigt werden muss .DateTime.UtcNow hat normalerweise eine Auflösung von 15 ms. Eine großartige Zusammenfassung finden Sie in John Chapmans Blogbeitrag über
DateTime.Now
Präzision.Interessante Trivia: Die Stoppuhr
DateTime.UtcNow
greift zurück, wenn Ihre Hardware keinen Hochfrequenzzähler unterstützt. Sie können anhand des statischen Felds Stopwatch.IsHighResolution überprüfen, ob Stopwatch Hardware verwendet, um eine hohe Präzision zu erzielen .quelle
PerformWork()
sehr kurz ist, möglicherweise wiederholt anrufen und den Durchschnitt der Anzahl der Anrufe berechnen können. Planen Sie außerdem eine ganze Reihe von Anrufen, anstatt Sie zu starten / zu stoppenStopwatch
, um einen Strobe-Effekt zu vermeiden, der Ihre Timing-Messungen trübt.Wenn Sie etwas schnelles und schmutziges wollen, würde ich empfehlen, stattdessen Stoppuhr zu verwenden, um ein höheres Maß an Präzision zu erzielen.
Wenn Sie etwas anspruchsvolleres benötigen, sollten Sie alternativ einen Profiler eines Drittanbieters wie ANTS verwenden .
quelle
In diesem Artikel heißt es, dass Sie zunächst drei Alternativen vergleichen müssen
Stopwatch
,DateTime.Now
UNDDateTime.UtcNow
.Es zeigt auch, dass Stoppuhr in einigen Fällen (wenn kein Leistungsindikator vorhanden ist) DateTime.UtcNow + eine zusätzliche Verarbeitung verwendet. Aus diesem Grund ist es offensichtlich, dass in diesem Fall DateTime.UtcNow die beste Option ist (weil andere es verwenden + etwas Verarbeitung)
Wie sich jedoch herausstellt, ist der Zähler fast immer vorhanden - siehe Erläuterung zum hochauflösenden Leistungsindikator und seiner Existenz im Zusammenhang mit .NET-Stoppuhr? .
Hier ist ein Leistungsdiagramm. Beachten Sie, wie niedrig die Leistungskosten von UtcNow im Vergleich zu Alternativen sind:
Die X-Achse ist die Größe der Probendaten und die Y-Achse ist die relative Zeit des Beispiels.
Eine Sache
Stopwatch
ist besser darin, dass es Zeitmessungen mit höherer Auflösung bietet. Ein weiterer Grund ist die eher OO-Natur. Das Erstellen eines OO-WrappersUtcNow
kann jedoch nicht schwierig sein.quelle
Es ist nützlich, Ihren Benchmarking-Code in eine Dienstprogrammklasse / -methode zu verschieben. Die
StopWatch
Klasse muss nichtDisposed
oderStopped
fehlerhaft sein. So ist die einfachste Code zu Zeit einige Aktion istBeispiel für einen Anrufcode
Hier ist die Version der Erweiterungsmethode
Und Beispiel für einen Anrufcode
quelle
Elapsed.TotalMilliseconds
für eine höhere Präzision. Siehe diese Frage auch stackoverflow.com/questions/8894425/…Die Stoppuhrfunktionalität wäre besser (höhere Präzision). Ich würde jedoch auch empfehlen, nur einen der beliebten Profiler herunterzuladen ( DotTrace und ANTS sind diejenigen, die ich am häufigsten verwendet habe ... die kostenlose Testversion für DotTrace ist voll funktionsfähig und nervt nicht wie einige der anderen).
quelle
Verwenden Sie die System.Diagnostics.Stopwatch-Klasse.
quelle
Das Gleiche gilt für Stoppuhr. Es ist viel besser.
In Bezug auf die Leistungsmessung sollten Sie auch prüfen, ob Ihr "// Some Execution Process" ein sehr kurzer Prozess ist.
Denken Sie auch daran, dass der erste Lauf Ihres "// Some Execution Process" möglicherweise viel langsamer ist als die nachfolgenden Läufe.
Normalerweise teste ich eine Methode, indem ich sie 1000-mal oder 1000000-mal in einer Schleife ausführe, und ich erhalte viel genauere Daten als einmal.
quelle
Dies sind alles großartige Möglichkeiten, um die Zeit zu messen, aber dies ist nur eine sehr indirekte Methode, um Engpässe zu finden.
Der direkteste Weg, um einen Engpass in einem Thread zu finden, besteht darin, ihn zum Laufen zu bringen. Während er alles tut, was Sie warten lässt, halten Sie ihn mit einer Pause oder einer Unterbrechungstaste an. Mach das mehrmals. Wenn Ihr Engpass X% der Zeit in Anspruch nimmt, ist X% die Wahrscheinlichkeit, dass Sie ihn bei jedem Schnappschuss auf frischer Tat ertappen.
Hier finden Sie eine ausführlichere Erklärung, wie und warum es funktioniert
quelle
@ Sean Chambers
Zu Ihrer Information, die .NET Timer-Klasse ist nicht für die Diagnose vorgesehen. Sie generiert Ereignisse in einem voreingestellten Intervall wie diesem (von MSDN ):
Das hilft dir also wirklich nicht zu wissen, wie lange etwas gedauert hat, nur dass eine gewisse Zeit vergangen ist.
Der Timer wird auch als Steuerelement in System.Windows.Forms ... angezeigt. Sie finden ihn in Ihrer Designer-Toolbox in VS05 / VS08
quelle
Das ist der richtige Weg:
Weitere Informationen finden Sie unter Verwenden Sie Stoppuhr anstelle von DataTime, um einen genauen Leistungsindikator zu erhalten .
quelle
Visual Studio Team System verfügt über einige Funktionen, die bei diesem Problem hilfreich sein können. Im Wesentlichen können Sie Komponententests schreiben und diese in verschiedenen Szenarien mischen, um sie im Rahmen eines Stress- oder Belastungstests mit Ihrer Software auszuführen. Dies kann dazu beitragen, Codebereiche zu identifizieren, die sich am stärksten auf die Leistung Ihrer Anwendungen auswirken.
Die Gruppe "Muster und Vorgehensweisen" von Microsoft enthält einige Anleitungen in den Anleitungen zum Testen der Systemleistung von Visual Studio Team .
quelle
Ich habe gerade in Vance Morrisons Blog einen Beitrag über eine von ihm geschriebene CodeTimer-Klasse gefunden , die die Verwendung
StopWatch
erleichtert und nebenbei einige nette Dinge erledigt.quelle
Das ist nicht professionell genug:
Eine zuverlässigere Version ist:
In meinem realen Code füge ich einen GC.Collect-Aufruf hinzu, um den verwalteten Heap in einen bekannten Status zu ändern, und füge einen Sleep-Aufruf hinzu, damit verschiedene Codeintervalle im ETW-Profil leicht getrennt werden können.
quelle
Ich habe sehr wenig von dieser Art der Leistungsprüfung gemacht (ich denke eher "das ist langsam, mach es schneller"), also habe ich mich so ziemlich immer damit beschäftigt.
Ein Google enthüllt viele Ressourcen / Artikel für die Leistungsprüfung.
Viele erwähnen die Verwendung von Pinvoke, um Leistungsinformationen zu erhalten. Viele der Materialien, die ich studiere, erwähnen nur die Verwendung von Perfmon.
Bearbeiten:
Gesehen die Gespräche von StopWatch .. Schön! Ich habe etwas gelernt :)
Das sieht nach einem guten Artikel aus
quelle
In meinen Programmen verwende ich die hier gezeigte StopWatch-Klasse.
quelle