Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does DateTime.Now and StopWatch drift?

Tags:

c#

I made a small test application in C# that sets DateTime.Now and starts a StopWatch. Every ten seconds I print _stopwatch.Elapsed.TotalMilliseconds and (DateTime.Now - _startTime).TotalMilliseconds.

While I don't expect the two to be identical, I was surprised to see them diverge linearly by about one millisecond per 20 seconds. I assume DateTime.Now calls the system clock, while the StopWatch does some kind of accumulation?

Sample output:

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

Full source: https://gist.github.com/knatten/86529563122a342de6bb

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

like image 969
knatten Avatar asked Apr 30 '14 14:04

knatten


1 Answers

The answer is relatively straight forward.

  • Stopwatch counts processor ticks using a performance counter, a mechanism that varies between processors.
  • DateTime queries the system clock - the system clock is updated periodically by windows using output from the (probably quartz) crystal clock on your motherboard.

All clocks drift and these two different timing mechanisms will drift at different rates.

Under the hood, Stopwatch uses this API

The Stopwatch class assists the manipulation of timing-related performance counters within managed code. Specifically, the Frequency field and GetTimestamp method can be used in place of the unmanaged Win32 APIs QueryPerformanceFrequency and QueryPerformanceCounter.

DateTime uses this API

like image 96
Gusdor Avatar answered Sep 22 '22 14:09

Gusdor