Messen Sie die Ausführungszeit in C #
-
29-09-2019 - |
Frage
Ich mag die Ausführung eines Stück Code messen und ich frage mich, was die beste Methode, dies zu tun ist?
Option 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");
Option 2: using System.Diagnostics;
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");
Das ist nicht nur für das Benchmarking, sein eigentlich Teil der Anwendung. Die Zeit, die Funktion auszuführen braucht ist relevante Daten. Es ist jedoch nicht braucht atomare oder hyper genau zu sein.
Welche Option ist besser für die Produktion Code, oder hat jemand anderes Gebrauch etwas anders und vielleicht besser?
Lösung
Die Stopwatch
Klasse ist speziell verstrichene Zeit zu messen und kann (falls vorhanden auf Ihrer Hardware) sorgt für eine gute Körnigkeit / Genauigkeit eines darunter liegende Hochfrequenz Hardware Timer. So dies scheint die beste Wahl.
Die IsHighResolution Eigenschaft kann verwendet werden, um zu bestimmen, ob die verfügbare hohe Auflösung Timing ist. Per der Dokumentation dieser Klasse bietet ein Wrapper auf die ‚besten verfügbaren‘ Win32-APIs für genaues Timing:
Insbesondere das
Frequency
Feld undGetTimestamp
Verfahren kann verwendet werden, Anstelle des nicht verwalteten Win32-APIsQueryPerformanceFrequency
undQueryPerformanceCounter
.
Es gibt detaillierten Hintergrund auf derjenigediejenigedasjenige Win32-APIs [hier] und in verknüpften MSDN-Dokumentation 2 .
High-Resolution Timer
Ein Zähler ist ein allgemeiner Begriff verwendet, in Programmierung auf einen Bezug zu nehmen Erhöhen variabel. einige Systeme umfassen eine hochauflösende Leistung Zähler, der mit hohen Auflösung liefert verflossenen Zeiten.
Wenn eine hochauflösende Leistung Zähler auf dem System vorhanden, können Sie Verwenden Sie die Queryperformance dazu dienen, die Frequenz zu exprimieren, in Zählungen pro Sekunde. Der Wert der Zählung Prozessor abhängig. auf einigen Prozessoren, beispielsweise die Zählung könnte die Taktrate der sein Prozessortakt.
Die Queryperformancecounter Funktion empfängt den aktuellen Wert der hochauflösende Leistungsindikator. Durch den Aufruf dieser Funktion bei der Anfang und Ende eines Abschnittes Code, im wesentlichen eine Anwendung der Zähler als ein hochauflösendes Timer. Zum Beispiel: Angenommen, Queryperformance zeigt dass die Frequenz des hochauflösende Leistungsindikator ist 50.000 Zählungen pro Sekunde. wenn die Anwendungsaufrufe Queryperformancecounter sofort vor und unmittelbar nach dem Codeabschnitt zeitlich gesteuert werden, die Zählerwerte könnten 1500 Zählungen und 3500 Zählungen sind. Diese Werte würden zeigen, dass 0,04 Sekunden (2000 Counts) verstrichen, während der Code ausgeführt wird.
Andere Tipps
Es ist nicht nur, dass StopWatch
genauer ist, sondern auch, dass DateTime.Now
falsche Ergebnisse unter Umständen geben wird.
Überlegen Sie, was während eines Tageslicht geschieht das spart Zeit Umschaltung zum Beispiel - mit DateTime.Now
kann tatsächlich geben eine negativ Antwort
ich in der Regel StopWatch
für diese Art von Situation verwendet werden.
MSDN Seite:
Stoppuhr
Stellt eine Reihe von Methoden und Eigenschaften, die Sie verwenden können genau die abgelaufene Zeit messen.
Im folgenden Beitrag habe ich es verwenden, um die Ausführungszeit von LINQ vs PLINQ zu vergleichen:
Weder wird die Leistung weh tun, weil Sie sagen, es ist nicht so kritisch. Stopwatch scheint besser geeignet - Sie sind nur die Zeit von Zeit subtrahiert wird und nicht ein Datum von einem anderen. Datum Sachen dauert ein bisschen mehr Speicher und CPU-Zeit zu beschäftigen. Es gibt auch Möglichkeiten, den Code sauberer zu machen, falls Sie planen, es in mehreren Orten auf Wiederverwendung. Eine Überlastung using
in den Sinn kommt. Ich werde für ein Beispiel suchen. Ok, Code gestohlen aus:
http://stevesmithblog.com/blog/great -Verwendet-of-using-statement-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);
}
}
Beide werden wahrscheinlich Ihre Bedürfnisse passen ganz gut, aber ich würde die Verwendung StopWatch
sagen. Warum? Weil es für die Aufgabe gemeint Sie tun.
Sie haben eine Klasse bekommen, die die aktuelle Datum / Zeit zurückzukehren gebaut ist, das, wie es kann geschieht für Timing Dinge verwendet werden, und Sie haben eine Klasse bekommen speziell für Timing Dinge.
In diesem Fall ist die Unterschiede nur dann wirklich, wenn Sie Millisekunde Genauigkeit benötigen (in diesem Fall StopWatch
ist genauer), sondern als allgemeines Prinzip, wenn ein Werkzeug vorhanden ist speziell für die Aufgabe Sie suchen, dann ist es die bessere zu Verwendung.
habe ich eine wenig Klasse, um diese Art der Sache zu tun ad hoc. Es nutzt die Stoppuhr Klasse - c # micro perfomance Testen .
zB.
var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
Verwenden Sie den folgenden Code
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();
habe ich Hamish Antwort es vereinfacht und es etwas allgemeiner, falls Sie irgendwo anmelden müssen anders:
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);
}
}