【问题标题】:How accurate is System.Diagnostics.Stopwatch?System.Diagnostics.Stopwatch 的准确性如何?
【发布时间】:2010-09-28 11:38:30
【问题描述】:

System.Diagnostics.Stopwatch 的准确性如何?我正在尝试为不同的代码路径做一些指标,我需要它是准确的。我应该使用秒表还是有其他更准确的解决方案。

有人告诉我,有时秒表会提供不正确的信息。

【问题讨论】:

  • 毫秒精度够吗?应该足以满足您的目的。定义“准确”。
  • 我知道它可以给你几毫秒,但我被告知在很多情况下它不准确
  • 永远不要依赖对任何事物的单一测量来确保准确性。运行每个代码路径几分钟并计算迭代次数以获得平均值。
  • 我已经写了一篇关于这个的文章。它显示了如何从秒表类中获得良好的测量结果:codeproject.com/KB/testing/stopwatch-measure-precise.aspx
  • 顺便说一句,由于这是一个非常古老的问题,在较新的硬件上运行的较新的 .NET 中,秒表的准确性要好得多,因为(正如 Lee Grisholm 在对 Kernelman 答案的评论中所说),它是现在是 QueryPerformanceCounter 的包装器。

标签: c# .net performance stopwatch


【解决方案1】:

System.Diagnostics.Stopwatch 类确实可以准确测量经过的时间,但是 ElapsedTicks 方法的工作方式导致一些人得出结论,即它不准确,而实际上他们的代码中确实存在逻辑错误。

一些开发人员认为秒表不准确的原因是秒表中的 ElapsedTicks 不等于 DateTime 中的刻度。 当应用程序代码使用 ElapsedTicks 创建新的 DateTime 时,就会出现问题。

var watch = new Stopwatch();
watch.Start();
... (perform a set of operations)
watch.Stop();
var wrongDate = new DateTime(watch.ElapsedTicks); // This is the WRONG value.

如果需要,可以通过以下方式将秒表持续时间转换为 DateTime:

// This converts stopwatch ticks into DateTime ticks.
// First convert to TimeSpan, then convert to DateTime
var rightDate = new DateTime(watch.Elapsed.Ticks); 

这里有一篇文章更详细地解释了这个问题: http://geekswithblogs.net/BlackRabbitCoder/archive/2012/01/12/c.net-little-pitfalls-stopwatch-ticks-are-not-timespan-ticks.aspx

【讨论】:

    【解决方案2】:

    我刚刚写了一篇文章,解释了必须如何进行测试设置才能从秒表中获得高精度(优于 0.1 毫秒)。我认为它应该解释一切。

    http://www.codeproject.com/KB/testing/stopwatch-measure-precise.aspx

    【讨论】:

    • 秒是小写的 s。毫秒不是毫秒。 en.wikipedia.org/wiki/Second#SI_multiples(与您的文章相同)
    • 您的文章与 MS 在这里所说的有些矛盾:msdn.microsoft.com/en-us/library/windows/desktop/…MSDN。他们声称对于大多数硬件,Stopwatch() 是最快和准确的,特别是对于多处理器 CPU 和频率变化 CPU(我猜这是最现代的 CPU)。你仍然认为值得在一个线程上运行 time-manamgent(如果可能的话)吗?
    【解决方案3】:

    首先,在谈论时间或空间时,精确当然不是一个可能或有意义的概念,因为任何物理量级的经验测量都不能假装是精确的。

    其次,David Bolton 的博客文章可能有用。我在引用:

    如果这是用高分辨率计数器计时的,那么它将精确到微秒。它实际上是精确到纳秒(10-9 秒,即十亿分之一秒),但是还有很多其他的东西,纳秒精度真的有点毫无意义。在对代码进行计时或基准测试时,您应该进行多次运行并取平均时间——因为在 Windows 下运行的其他进程、正在发生多少交换到磁盘等,两次运行之间的值可能会有所不同。

    【讨论】:

    • 主要问题不是磁盘 I/O,实际上是线程上下文切换。随着 .NET 框架和 Windows 的更新版本,这个问题变得不那么重要了,但它仍然存在。
    【解决方案4】:

    如果您想要更精确的时间。看看 QueryPerformanceCounter。 QueryPerformanceCounter 的 MSDN 链接。 here 给出了一个简洁的实现。该示例为 CE 加载 coredll.dll,对于 Windows,您应该加载 Kernel32.dll,如 MSDN 文档中所述。

    【讨论】:

    • 查看 Stopwatch 类的源代码(使用 .NET Reflector),它已经是 QueryPerformanceCounter 的一个非常薄的包装器。
    【解决方案5】:

    为什么您不分析您的代码,而是专注于微基准测试?

    有一些不错的开源分析器,例如:

    【讨论】:

    • 请注意,Google Code 上的 NProf 网站显示 NProf 不再处于开发阶段——它建议改为使用 SlimTune
    • 有用的信息,但这是另一个问题的答案。
    • 如前所述,这不能回答问题。
    • 对 cme​​ts 的回答为“..不回答问题”:相反。这回答了这个问题,如果您阅读它:“我应该使用秒表还是有另一种更准确的解决方案”。它只是不回答问题的标题。除此之外,这里有些人(如我)将改进建议视为重要且受欢迎的答案,对我而言,这还包括对替代解决方案的引用。我有一些问题要理解,为什么这里似乎没有几个人需要批评(?)
    • @Philm:同意,但不幸的是,这是“C# 秒表分辨率”的最高 Google 搜索结果
    【解决方案6】:

    秒表类在不同的配置下返回不同的值,因为频率取决于安装的硬件和操作系统。

    使用秒表类,我们只能粗略估计执行时间。对于每次执行,它返回不同的值,所以我们必须取不同执行的平均值。

    更多信息:http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

    【讨论】:

      【解决方案7】:

      除了支持上述 HUAGHAGUAH 的建议之外,我还要补充一点,一般来说,您应该对微基准非常怀疑。虽然密切关注的性能测试有一个合法的位置,但很容易调整一个不重要的细节。因此,编写并验证专为可读性和清晰性而设计的代码,然后对其进行分析以找出热点在哪里(或者是否有值得担心),然后(仅)调整这些部分.

      我记得曾与一位程序员一起工作,他对系统等待人工输入时执行的一些代码进行了微优化。节省的时间在击键之间的延迟中完全消失了!

      【讨论】:

        【解决方案8】:

        MSDN 有秒表的some examples。他们还用它来显示它在纳秒内的准确度。希望这会有所帮助!

        【讨论】:

        • 我运行了他们的示例代码。它说它可以精确到 0 纳秒内,并给我一个测试的 -657 毫秒的结果。不是很有帮助!
        • 精度和准确度不是一回事。您的计算机没有纳秒精度。它甚至没有毫秒精度。
        • 是的。并非总是如此,但最近的计算机使用 RDTSC CPU 指令。它可以精确到 CPU 的频率(如 3 GHz)。但是,我遇到了一些新硬件的问题,其中 StopWatch.Frequency 约为 2MHz(所以我猜测 Windows 正在主板上使用其他时钟),但由于某种原因,频率不是很稳定,导致错误到毫秒...这就是为什么我正在浏览stackoverflow。
        猜你喜欢
        • 2015-08-13
        • 2013-12-24
        • 2010-11-14
        • 1970-01-01
        • 1970-01-01
        • 2010-09-24
        • 1970-01-01
        • 2020-12-08
        相关资源
        最近更新 更多