493 Stimmen

Ist DateTime.Now der beste Weg, um die Leistung einer Funktion zu messen?

Ich muss einen Engpass finden und die Zeit so genau wie möglich messen.

Ist der folgende Code-Schnipsel der beste Weg, um die Leistung zu messen?

DateTime startTime = DateTime.Now;

// Einige Ausführungsprozesse

DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);

0 Stimmen

Übrigens, wenn Sie nicht auf der Suche nach etwas Schnellem und Dreckigem sind, können Leistungsindikatoren verwendet werden.

1 Stimmen

Wenn Sie eine größere Genauigkeit benötigen, verwenden Sie Stopwatch.GetTimestamp, ansonsten ist die Antwort gut.

0 Stimmen

@dbasnett Können Sie in einer Antwort mehr ins Detail gehen?

670voto

Markus Olsson Punkte 21942

Nein, ist es nicht. Verwenden Sie die Stoppuhr (in System.Diagnostics)

Stoppuhr sw = Stoppuhr.StartNew();
FühreArbeitAus();
sw.Stop();

Console.WriteLine("Benötigte Zeit: {0}ms", sw.Elapsed.TotalMilliseconds);

Die Stoppuhr überprüft automatisch das Vorhandensein von hochauflösenden Timern.

Es ist erwähnenswert, dass DateTime.Now oft deutlich langsamer ist als DateTime.UtcNow aufgrund der Arbeiten, die mit Zeitzonen, DST und dergleichen durchgeführt werden müssen.

DateTime.UtcNow hat in der Regel eine Auflösung von 15 ms. Lesen Sie den Blog-Post von John Chapman über die Präzision von DateTime.Now für eine gute Zusammenfassung.

Interessante Trivia: Die Stoppuhr greift auf DateTime.UtcNow zurück, wenn Ihre Hardware keinen Hochfrequenzzähler unterstützt. Sie können prüfen, ob die Stoppuhr Hardware verwendet, um hohe Präzision zu erreichen, indem Sie das statische Feld Stopwatch.IsHighResolution betrachten.

95voto

mmcdole Punkte 88559

Wenn Sie etwas Schnelles und Einfaches möchten, würde ich empfehlen, anstelle davon Stopwatch zu verwenden, um eine größere Genauigkeit zu erzielen.

Stopwatch sw = new Stopwatch();
sw.Start();
// Arbeit erledigen
sw.Stop();

Console.WriteLine("Verstrichene Zeit: {0}", sw.Elapsed.TotalMilliseconds);

Alternativ, wenn Sie etwas anspruchsvolleres benötigen, sollten Sie wahrscheinlich in Betracht ziehen, ein 3rd-Party-Tool wie ANTS zu verwenden.

60voto

Valentin Kuzub Punkte 10967

Dieser Artikel sagt, dass Sie zunächst drei Alternativen vergleichen müssen: Stopwatch, DateTime.Now UND DateTime.UtcNow.

Es zeigt auch, dass in einigen Fällen (wenn Leistungsindikator nicht existiert) Stopwatch DateTime.UtcNow + einige weitere Verarbeitung verwendet. Daher ist es offensichtlich, dass in diesem Fall DateTime.UtcNow die beste Option ist (weil andere sie verwenden + einige Verarbeitung)

Allerdings stellt sich heraus, dass der Leistungsindikator fast immer vorhanden ist - siehe Erklärung zum hochauflösenden Leistungsindikator und dessen Existenz in Bezug auf .NET Stopwatch?.

Hier ist ein Leistungsdiagramm. Beachten Sie, wie gering die Leistungskosten von UtcNow im Vergleich zu Alternativen sind:

Geben Sie hier eine Bildbeschreibung ein

Die X-Achse ist die Beispieldatengröße und die Y-Achse ist die relative Zeit des Beispiels.

Eine Sache, in der Stopwatch besser ist, ist, dass sie eine höhere Auflösung bei der Zeitmessung bietet. Ein weiterer Vorteil ist ihre stärker objektorientierte Natur. Es kann jedoch nicht schwierig sein, eine OO-Wrapper um UtcNow zu erstellen.

19voto

Anthony Mastrean Punkte 20992

Es ist nützlich, Ihren Benchmarking-Code in einer Hilfsklasse/Methode zu platzieren. Die StopWatch-Klasse muss im Fehlerfall nicht Disposed oder Stopped sein. Also ist der einfachste Code, um eine Aktion zu zeitlich zu erfassen:

public partial class With
{
    public static long Benchmark(Action action)
    {
        var stopwatch = Stopwatch.StartNew();
        action();
        stopwatch.Stop();
        return stopwatch.ElapsedMilliseconds;
    }
}

Beispielaufrufscode

public void Execute(Action action)
{
    var time = With.Benchmark(action);
    log.DebugFormat(“Aktion in {0} ms durchgeführt.”, time);
}

Hier ist die Erweiterungsmethodenversion

public static class Extensions
{
    public static long Benchmark(this Action action)
    {
        return With.Benchmark(action);
    }
}

Und Beispielaufrufscode

public void Execute(Action action)
{
    var time = action.Benchmark()
    log.DebugFormat(“Aktion in {0} ms durchgeführt.”, time);
}

18voto

jsight Punkte 27087

Die Stoppuhr-Funktionalität wäre besser (höhere Präzision). Ich würde auch empfehlen, einfach einen der beliebten Profiler herunterzuladen, jedoch (DotTrace und ANTS sind die, die ich am häufigsten benutzt habe... die kostenlose Testversion von DotTrace ist voll funktionsfähig und nervt nicht wie einige andere).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X