为什么DateTime.Now和StopWatch会漂移?

时间:2014-04-30 14:16:01

标签: c#

我在C#中创建了一个小型测试应用程序,用于设置DateTime.Now并启动StopWatch。我每十秒钟打印_stopwatch.Elapsed.TotalMilliseconds(DateTime.Now - _startTime).TotalMilliseconds

虽然我不认为这两者是完全相同的,但我惊讶地看到它们每20秒线性地发散约1毫秒。我假设DateTime.Now调用系统时钟,而StopWatch进行某种积累?

示例输出:

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

完整来源:https://gist.github.com/knatten/86529563122a342de6bb

输出:https://gist.github.com/knatten/84f9be9019ee63119ee2

3 个答案:

答案 0 :(得分:3)

每隔几毫秒

DateTime.Now滴答。此外,它在一个机器之间的固定速率并不固定。在现代Windows系统机器上,您可以预期刻度分辨率大约为每秒100个刻度。

另一方面,StopWatch查询CPU硬件以获得高精度。实际上,您可以使用StopWatch获得Stopwatch.Frequency的分辨率。

我不知道上述两点,直到我读了Eric Lippert的一篇有趣的帖子,关于常见的性能基准测试错误,请看这里here。这真是一个很棒的职位。

答案 1 :(得分:3)

答案相对简单。

  • 秒表使用性能计数器对处理器滴答进行计数,这是一种因处理器而异的机制。
  • DateTime查询系统时钟 - 系统时钟由Windows使用主板上(可能是石英)水晶时钟的输出定期更新。

所有时钟漂移,这两种不同的定时机制将以不同的速率漂移。

幕后,Stopwatch uses this API

  

秒表课程有助于操纵与时间相关的操作   托管代码中的性能计数器。具体来说,频率   可以使用字段和GetTimestamp方法代替非托管方法   Win32 API QueryPerformanceFrequency和QueryPerformanceCounter。

DateTime uses this API

答案 2 :(得分:2)

Stopwatch比考虑差异的DateTime精确得多

来自MSDN

  

秒表通过计算基础计时器机制中的计时器滴答来测量经过的时间。如果安装的硬件和操作系统支持高分辨率性能计数器,则Stopwatch类使用该计数器来测量经过的时间。否则,Stopwatch类使用系统计时器来测量经过的时间。使用Frequency和IsHighResolution字段确定秒表计时实施的精度和分辨率。