2014-04-30 15 views
8

Zrobiłem małą aplikację testową w języku C#, która ustawia DateTime.Now i rozpoczyna StopWatch. Co dziesięć sekund drukuję _stopwatch.Elapsed.TotalMilliseconds i (DateTime.Now - _startTime).TotalMilliseconds.Dlaczego drift DateTime.Now i StopWatch?

Chociaż nie oczekuję, że te dwa elementy będą identyczne, byłem zaskoczony widząc ich rozbieżność liniową o około jedną milisekundę na 20 sekund. Zakładam, że DateTime.Now dzwoni do zegara systemowego, podczas gdy StopWatch robi jakiś rodzaj akumulacji?

Przykładowe wyjście:

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 

Pełna źródło: https://gist.github.com/knatten/86529563122a342de6bb

wyjściowa: https://gist.github.com/knatten/84f9be9019ee63119ee2

+0

myśleć o tym ... nie można nazwać ich obu w tej samej linii w dokładnie tym samym czasie ... tak tak, w swoim zegarem, czas potrzebny do wydrukuj informacje dla datetime, a następnie wydrukować informacje dla StopWatch, niezależnie od tego, jak blisko są połączenia (jeden po drugim), w ciągu 20 sekund, pokaże względnie małą różnicę (1 ms) ... – MaxOvrdrv

+4

@MaxOvrdrv Chociaż może to być dla początkowej różnicy nie spowodowałaby zgodnego dryfu, jak określono w PO. – Ashigore

+1

@Ashigore masz rację ... to powinna być ta sama różnica widoczna na wszystkich wydrukach ... nie wiem wtedy ... może jego wewnętrzna bateria zegara jest na wyczerpaniu? ;) – MaxOvrdrv

Odpowiedz

3

Odpowiedź jest stosunkowo prosta.

  • Stoper liczy tykle procesora za pomocą licznika wydajności, mechanizmu zmieniającego się między procesorami.
  • DateTime odpytuje zegar systemowy - zegar systemowy jest okresowo aktualizowany przez okna z wykorzystaniem wyjścia z (prawdopodobnie kwarcowego) zegara kryształowego na płycie głównej.

Wszystkie zegary dryfują i te dwa różne mechanizmy pomiaru czasu będą dryfować z różnymi prędkościami.

Pod maską Stopwatchuses this API

Klasa Stoper pomaga manipulacji związanych z przejściowymi-liczników wydajności w całym kodzie zarządzanym.W szczególności pole Frequency i GetTimestamp mogą być używane zamiast niezarządzanych interfejsów API Win32 API QueryPerformanceFrequency i QueryPerformanceCounter.

DateTimeuses this API

+2

Nie tylko zegary fizyczne dryfują, ale także DateTime. (Utc) Teraz można dodatkowo uzyskać dostosowanie do źródła czasu sieciowego. Zobacz np. [Odpowiedź Hansa Passanta] (http://stackoverflow.com/a/19736972/709537) na podobne pytanie. –

3

DateTime.Now kleszcze co kilka milisekund. Ponadto szybkość, z jaką tyka nie jest ustalana z komputera na maszynę. Na nowoczesnych maszynach z systemami Windows można oczekiwać, że rozdzielczość kleszczy wyniesie około 100 tików na sekundę.

Z drugiej strony, StopWatch zapytuje sprzęt procesora, aby uzyskać wysoką dokładność. W rzeczywistości można uzyskać rozdzielczość StopWatch przy użyciu Stopwatch.Frequency.

Nie znałem obu powyższych, dopóki nie przeczytałem interesującego posta Erica Lipperta, o typowych błędach testów wydajności, proszę spojrzeć tutaj here. To naprawdę świetny post.

+0

Tycząc, masz na myśli, że DateTime.Now tyka i akumuluje? Spodziewam się, że zapyta o zegar systemowy. – knatten

+0

Jak rozumiem, zarówno DateTime.Now, jak i StopWatch, ale w różnych stawkach. – Christos

+0

Oni zaznaczają na różnych stawkach, ale wydaje się, że Stoper gromadzi tyknięcia, podczas gdy DateTime ponownie sprawdza czas systemowy, patrz odpowiedź Gusdora. – knatten

2

Stopwatch jest znacznie bardziej precyzyjne niż DateTime które stanowią rozbieżności

Od MSDN:

Stoper mierzy czas, jaki upłynął od liczenia licznik kleszczy w mechanizmie zegara bazowego. Jeśli zainstalowany sprzęt i system operacyjny obsługują licznik wydajności o wysokiej rozdzielczości, wówczas klasa Stoper używa tego licznika do mierzenia czasu, który upłynął. W przeciwnym razie klasa Stopwatch używa licznika czasu do pomiaru upływu czasu. Użyj pól Frequency i IsHighResolution, aby określić dokładność i rozdzielczość implementacji taktowania stopera.

+0

Stoper jest dokładniejszy, ale który z nich jest dokładniejszy? Czy oba gromadzą kleszcze, czy też DateTime. Czy zapytasz zegar systemowy? W takim przypadku możemy mieć bardziej precyzyjny Stoper, ale dokładniejszy DateTime. – knatten

+1

Dokładność zależy od konfiguracji sprzętowej. – Gusdor

Powiązane problemy