是DateTime.Now是一个I / O绑定操作?

时间:2016-06-05 15:16:10

标签: c# .net datetime

致电DateTime.Now时会发生什么?

我按照Reflector中的属性代码,它似乎将当前区域设置的时区偏移添加到UtcNow。在UTCNow引导我之后,轮流转向,最后转到Win32 API调用。

我反思并问a related question但尚未得到满意的答复。从目前评论中关于该问题的链接,我推断有一个硬件单元可以保留时间。但我也想知道它保留了什么单位以及它是否使用CPU将时间转换为人类可读单元。这将揭示日期和时间信息的检索是I / O绑定还是计算绑定。

3 个答案:

答案 0 :(得分:35)

对于这个问题,你处于无证领域。时间由内核提供:底层本机API调用是NtQuerySystemTime()。这个确实在Windows版本中被修改 - Windows 8特别严重地改变了底层实现,带来了明显的副作用。

本质上是I / O限制:时间由RTC(实时时钟)维护,RTC曾经是专用芯片,但现在集成在芯片组中。但是有很强的证据表明它在实践中不受I / O约束。时间更新与时钟中断同步,因此中断处理程序很可能会读取RTC并获得值的副本。当您修改timeBeginPeriod()时,您可以看到一些东西。

您可以看到,当您对其进行分析时,它在Windows 10上只需要约7纳秒 - 完全太快而无法进行I / O限制。

答案 1 :(得分:4)

你似乎关心阻拦。有两种情况你想避免这种情况。

  1. 在UI线程上,它涉及延迟。无论你做什么(IO或CPU)都没关系,它可能需要很长时间。否则它会冻结UI线程。 UtcNow超级快,所以不是一个问题。
  2. 有时,非阻塞IO被用作扩展吞吐量的方法,因为添加了更多负载。这里,唯一的原因是保存线程,因为每个线程消耗大量资源。由于没有异步方式来调用UtcNow这个问题没有实际意义。你只需按原样调用它。
  3. 由于Windows上的时间通常以60 Hz的速度前进,因此我假设对UtcNow的调用是从写入60 Hz的内存变量中读取的。这使得CPU受到限制。但这两种方式无关紧要。

答案 2 :(得分:3)

.NET依赖于API。 MSDN必须说明API:

https://msdn.microsoft.com/de-de/library/windows/desktop/ms724961(v=vs.85).aspx

  

当系统首次启动时,它会根据计算机的实时时钟将系统时间设置为一个值,然后定期更新时间[...] GetSystemTime将时间复制到SYSTEMTIME [...]

我找不到可靠的来源来支持我声称它存储为SYSTEMTIME结构,在其中更新,并在调用时被复制到GetSystemTime的接收缓冲区。最小的逻辑单位是NtQuerySystemTime系统调用的100ns,但我们最终在CLR的DateTime对象中有1毫秒。分辨率并不总是相同的。

我们或许可以在Linux上为Mono弄清楚这一点,但鉴于API代码本身并不公开,我们很难为Windows解决这个问题。所以这是一个假设:当前时间是内核地址空间中的变量。它将由操作系统更新(通常由系统时钟计时器中断,更不频繁地来自网络源 - 文档提到呼叫者可能不依赖于单调行为,因为网络同步可以向后纠正当前时间)。操作系统将同步访问以防止并发写入,否则它将不会是I / O昂贵的操作。

在最近的计算机上,定时器间隔不再固定,可以由BIOS和OS控制。应用甚至可以请求更低或更高的时钟频率:https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted