2014-04-30 11 views
8

Ich habe eine kleine Testanwendung in C# gemacht, die DateTime.Now setzt und eine StopWatch startet. Alle zehn Sekunden drucke ich und (DateTime.Now - _startTime).TotalMilliseconds.Warum driften DateTime.Now und StopWatch?

Während ich nicht erwarte, dass die beiden identisch sind, war ich überrascht, dass sie linear um etwa eine Millisekunde pro 20 Sekunden divergieren. Ich nehme an, DateTime.Now ruft die Systemuhr, während die StopWatch eine Art von Akkumulation tut?

Beispielausgabe:

StopWatch : 0,2 DateTime : 1,0 Diff : 0,81 
StopWatch : 10000,5 DateTime : 10002,6 Diff : 2,04 
(...) 
StopWatch : 2231807,5 DateTime : 2231947,7 Diff : 140,13 
StopWatch : 2241809,5 DateTime : 2241950,2 Diff : 140,70 

Voll Quelle: https://gist.github.com/knatten/86529563122a342de6bb

Ausgang: https://gist.github.com/knatten/84f9be9019ee63119ee2

+0

darüber nachdenkt ... Sie können sie beide auf der gleichen Linie an genau der gleichen Zeit nicht nennen ... also ja, in Ihrem Timer, nimmt die Zeit, die zum Drucken Informationen für datetime, und DANN drucken die Informationen für StopWatch, unabhängig davon, wie nahe sie sind (einer nach dem anderen), über 20 Sekunden, zeigt eine relativ kleine Differenz (1 ms) ... – MaxOvrdrv

+4

@MaxOvrdrv Während dies möglicherweise Konto für einen anfänglichen Unterschied würde es keine konsistente Drift wie im OP angegeben verursachen. – Ashigore

+1

@Ashigore du hast Recht ... es sollte der gleiche Unterschied sein, der in allen Ausdrucken zu sehen ist ... ich weiß es nicht ... vielleicht ist seine interne Uhrbatterie schwach geworden? ;) – MaxOvrdrv

Antwort

3

Die Antwort ist relativ unkompliziert.

  • Stoppuhr zählt Prozessor Ticks mit einem Leistungsindikator, ein Mechanismus, der zwischen den Prozessoren variiert.
  • DateTime fragt die Systemuhr ab - die Systemuhr wird regelmäßig von Windows aktualisiert, wobei die Ausgabe der (wahrscheinlich Quarz-) Quarzuhr auf Ihrem Motherboard verwendet wird.
  • Alle Uhren driften und diese zwei verschiedenen Zeitsteuermechanismen werden mit unterschiedlichen Raten driften.

    Unter der Haube Stopwatchuses this API

    Die Stoppuhr-Klasse unterstützt die Manipulation von Timing bezogenen Leistungsindikatoren innerhalb verwalteten Code.Insbesondere kann das Feld "Frequency " und die Methode "GetTimestamp" anstelle der nicht verwalteten Win32-APIs QueryPerformanceFrequency und QueryPerformanceCounter verwendet werden.

    DateTimeuses this API

    +2

    Nicht nur die physikalischen Uhren driften, sondern DateTime. (Utc) Jetzt kann zusätzlich zu einer Netzwerkzeitquelle neu eingestellt werden. Siehe z.B. [Hans Passants Antwort] (http://stackoverflow.com/a/19736972/709537) auf eine ähnliche Frage. –

    3

    DateTime.Now alle paar Millisekunden Zecken. Außerdem ist die Geschwindigkeit, mit der es läuft, nicht von Maschine zu Maschine festgelegt. Auf modernen Windows-Systemen können Sie erwarten, dass die Tick-Auflösung bei 100 Ticks pro Sekunde liegt.

    Auf der anderen Seite fragt StopWatch die CPU-Hardware, um hohe Präzision zu erhalten. Tatsächlich können Sie die Auflösung StopWatch mit Stopwatch.Frequency erhalten.

    Ich kannte nicht beide oben, bis ich einen interessanten Beitrag von Eric Lippert über allgemeine Leistungsbenchmarkfehler las, bitte sieh hier here. Es ist wirklich ein toller Beitrag.

    +0

    Mit dem Ankreuzen meinen Sie, dass DateTime.Now ankreuzen und akkumulieren? Ich würde erwarten, dass es die Systemuhr abfragt. – knatten

    +0

    Wie ich verstanden habe, tickt sowohl DateTime.Now als auch StopWatch in unterschiedlichen Raten. – Christos

    +0

    Sie ticken mit unterschiedlichen Raten, aber es scheint, dass Stoppuhr Ticks akkumuliert, während DateTime die Systemzeit erneut abfragt, siehe Gusdors Antwort. – knatten

    2

    Stopwatch ist viel präziser als DateTime, die für die Diskrepanz

    Von MSDN erklären würde: durch Zählen Timerticks in dem zugrunde liegenden Mechanismus Timer verstrichene Zeit

    Die Stoppuhr misst. Wenn die installierte Hardware und das Betriebssystem einen hochauflösenden Leistungsindikator unterstützen, verwendet die Stoppuhrklasse diesen Indikator, um die verstrichene Zeit zu messen. Andernfalls verwendet die Stoppuhrklasse den Systemzeitgeber, um die verstrichene Zeit zu messen. Verwenden Sie die Felder "Frequency" und "IsHighResolution", um die Genauigkeit und Auflösung der Stoppuhr-Timing-Implementierung zu bestimmen.

    +0

    Also Stoppuhr ist genauer, aber welche ist genauer? Akzeptieren beide Ticks oder fragt DateTime.Now die Systemuhr ab? In diesem Fall haben wir vielleicht eine genauere Stoppuhr, aber eine genauere DateTime. – knatten

    +1

    Die Genauigkeit variiert zwischen den Hardwarekonfigurationen. – Gusdor

    Verwandte Themen