使用秒表和使用System.DateTime.Now来计时事件的区别

106

我想追踪代码的性能,因此使用 System.DateTime.Now 存储了开始和结束时间。我用两者之间的差异作为代码执行所需的时间。

然而,我注意到差异似乎不准确。所以我尝试使用一个 Stopwatch 对象。结果证明这要比计算使用 System.DateTime.Now 的开始和结束时间之间的差异更加精确得多。

有人可以告诉我为什么 Stopwatch 会比使用 System.DateTime.Now 计算开始和结束时间之间的差异更准确吗?

顺便说一下,我不是在讨论百分之十分之一的问题。我得到了大约 15-20% 的差异。


2
根据您对Kelsey答案的评论,我很想看到记录开始和结束时间的代码。11秒的差异(巨大)与两个类的精度差异无关,因此必须有其他原因。 - Igby Largeman
3
如果您只对两个日期之间的时间跨度感兴趣,通常最好使用DateTime.UtcNow而不是DateTime.Now,因为您通常不希望夏令时变化和其他本地时间差异影响结果。 - Daniel Pryden
@DanielPryden,请参阅反对使用DateTime.Now的理由,该文章正好阐述了这一观点。+1 - Matt Johnson-Pint
3个回答

87
根据 MSDN 的说明:
Stopwatch 通过计算底层计时器机制中的计时器滴答来测量经过的时间。如果安装的硬件和操作系统支持高分辨率性能计数器,则 Stopwatch 类使用该计数器来测量经过的时间。否则,Stopwatch 类使用系统计时器来测量经过的时间。使用 Frequency 和 IsHighResolution 字段来确定 Stopwatch 计时实现的精度和分辨率。
它比 DateTime.Now 使用更高的分辨率/精度。
你也可以查看以下相关链接: Environment.TickCount vs DateTime.Now Is DateTime.Now the best way to measure a function's performance? 对于精度到秒的情况,DateTime 可能已经足够好了,但是对于更高精度的情况,建议使用 Stopwatch。

37

最好使用Stopwatch类,因为它比减去DateTime值更准确:

Stopwatch s = Stopwatch.StartNew();
// Tested code here
s.Stop();
Console.WriteLine("Elapsed Time: {0} ms", s.ElapsedMilliseconds);

很不幸,这个简单的代码片段通常无法获得准确的测量结果,因为操作系统底层会有许多活动,这些活动可能会占用一些CPU时间并减缓代码执行速度。这就是为什么最好执行多次测试,然后去掉最低和最高时间。为此,一个好的解决方案是编写一个方法,多次执行测试代码,去掉最低和最高时间,计算平均时间。我在我的博客中发布了一个示例测试方法


我检查了你博客的链接。平均时间计算上有一个小错误。应该使用double averageTime = ((double)totalTime) / (count - (2*discardCount));而不是double averageTime = ((double)totalTime) / (count - discardCount);。对吗? - displayName
嗨,不应该有问题,博客中的代码是正确的。请看一下定义count的那一行。它被定义为:int count = repetitions - discardCount;。这就是为什么在计算平均时间时我只减去了discardCount一次(它已经被减去了一次)。祝好。 - Pavel Vladov
没错。没有注意到。你是对的。 - displayName
值得一提的是,另一种测量时间的方法是仅选择 N 次运行中的前 X 次。例如运行 5 次并选择最佳结果。毕竟,这是受操作系统干扰最少的结果。然而,这两种方法都有其优缺点。 - mirhagk

9
这个计时函数性能链接讨论了您的确切问题,特别是这一段:
问题在于,根据MSDN,DateTime.Now函数的分辨率为10+毫秒,而我们需要调用它两次!这将引入20+毫秒的运行时测量摆动。由于我们的函数调用通常比这20ms时间窗口更快返回,所以这还不够好。
编辑:听起来第二个DateTime.Now被调用的时间与停表方法结束的时间不同。

在这里:https://blogs.msdn.microsoft.com/ericlippert/2010/04/08/precision-and-accuracy-of-datetime/;Eric Lippert对DateTime的精度和准确性进行了很好的解释。最佳情况下为1/64秒。在开始和结束时进行两次调用,然后您将获得1/32秒的精度,可能会有约31毫秒的偏差。 - Ünsal Ersöz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接