C# 是DateTime。现在是I/O绑定操作吗?

C# 是DateTime。现在是I/O绑定操作吗?,c#,.net,datetime,C#,.net,Datetime,调用DateTime.Now时会发生什么 我遵循Reflector中的属性代码,它似乎将当前区域设置的时区偏移添加到UtcNow。接下来的UTCNow让我一个接一个地,终于找到了一个Win32 API调用 我对此进行了思考并提出了要求,但尚未收到令人满意的答复。从目前对这个问题的评论中的链接,我推断有一个硬件单元可以保持时间。但我还想知道它把时间放在什么单位,以及它是否使用CPU将时间转换成人类可读的单位。这将有助于了解日期和时间信息的检索是受I/O限制还是受计算限制。您似乎关心的是阻塞。有两种

调用
DateTime.Now
时会发生什么

我遵循Reflector中的属性代码,它似乎将当前区域设置的时区偏移添加到
UtcNow
。接下来的
UTCNow
让我一个接一个地,终于找到了一个Win32 API调用


我对此进行了思考并提出了要求,但尚未收到令人满意的答复。从目前对这个问题的评论中的链接,我推断有一个硬件单元可以保持时间。但我还想知道它把时间放在什么单位,以及它是否使用CPU将时间转换成人类可读的单位。这将有助于了解日期和时间信息的检索是受I/O限制还是受计算限制。

您似乎关心的是阻塞。有两种情况下,您希望避免这种情况

  • 在UI线程上,它是关于延迟的。不管你做什么(IO或CPU),都不会花很长时间。否则它将冻结UI线程
    UtcNow
    速度非常快,因此无需担心
  • 有时,随着负载的增加,非阻塞IO被用作扩展吞吐量的一种方法。在这里,唯一的原因是保存线程,因为每个线程都会消耗大量资源。因为没有异步方式调用
    UtcNow
    ,所以这个问题没有意义。你只要照原样说就行了

  • 由于Windows上的时间通常以60 Hz的频率前进,因此我假设对
    UtcNow
    的调用读取以60 Hz的频率写入的内存变量。这使得CPU受到限制。但是这两种方式都不重要。

    .NET依赖于API。MSDN必须对API这样说:

    当系统首次启动时,它将系统时间设置为基于计算机实时时钟的值,然后定期更新时间[…]GetSystemTime将时间复制到SYSTEMTIME[…]


    我没有找到可靠的来源来支持我的声明,即它存储为
    SYSTEMTIME
    结构,在其中进行了更新,并在调用时复制到
    GetSystemTime
    的接收缓冲区。最小的逻辑单元是距离系统调用100纳秒,但在CLR的
    DateTime
    对象中,我们以1毫秒结束。决心并不总是一样的

    对于Linux上的Mono,我们可能能够理解这一点,但对于Windows,由于API代码本身不是公开的,所以很难理解这一点。所以这里有一个假设:当前时间是内核地址空间中的一个变量。它将由操作系统进行更新(通常由系统时钟定时器中断进行更新,可能来自网络源的更新频率较低——文档中提到,呼叫者可能不依赖单调行为,因为网络同步可以向后修正当前时间)。操作系统将同步访问以防止并发写入,但否则这将不会是一个I/O代价高昂的操作


    在最近的计算机上,计时器间隔不再是固定的,可以由BIOS和操作系统控制。应用程序甚至可以请求更低或更高的时钟频率:

    您在这个问题上完全处于未记录的领域。时间由内核提供:底层本机API调用是
    NtQuerySystemTime()
    。这一点在不同的Windows版本中都得到了修正——Windows 8对底层的实现进行了特别重大的修改,并产生了明显的副作用

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


    当你对它进行分析时,你会发现在Windows 10上只需要7纳秒的时间,这对于I/O绑定来说太快了。

    IO和compute绑定是非常未定义的术语。你能澄清一下你感兴趣的属性或者你想要实现什么吗?我认为带date是I/O绑定的,用DateTime转换它。现在(它返回可读值对吗?)是计算绑定的。那么,这两个问题?@usr我无法回答您的调查,因为我对您的问题以及I/O和计算的概念了解有限,可能与您的问题所显示的深度有关。我不确定我想要什么。我只想知道会发生什么,这样我就可以计划如何调用
    DateTime。现在
    下次调用,这样我就不会阻塞它了,如果有的话。这只是我最近一直在思考的事情之一。@Ali我想你是对的。不过,我想知道更准确的细节。如果你能告诉我们它调用了什么Win32 API,你可以帮助我们给你更好的答案。开玩笑,有趣!你知道关于
    ~60Hz
    Windows时间进度的文章吗?我在谷歌上搜索过,但我得到的只是显示器的刷新率。它是64赫兹,而不是60赫兹。当你使用它时,频率往往是100赫兹,所以浏览器会对此进行修补:)在现代计算机上,频率变化很大。能源管理和应用程序可以对其进行调整。系统内部开发了一个工具来监控它:内置在Windows中,
    powercfg.exe/energy
    非常灵活。它在内核中,RTC可能是中断源。同样严重影响线程调度程序,上下文切换以中断速率发生。Sleep()最基本的原因就是它的准确度永远都比不上速率。更深入的未记录细节,不应影响您的编码方式。事实上,我相信RTC仅在引导时使用,然后内核使用其他计时器(可能是主CPU时钟)自行计时。@AndréBorie HPET使用不同的计时机制,目前在硬件中。如果不可用(旧硬件),则使用RTC和CPU计时器的组合。例如
    DateTime。现在
    Sleep
    使用RTC。实际上,您可以在循环中测试它,并在(iirc)15ms的间隔内看到值跳跃,这是RTC的典型情况