计时器在Windows 7之前合并

Windows 7和Windows 8中有定时器合并支持,例如见: 在.net中定时器合并
Windows 7有一个函数SetWaitableTimerEx ,声称它支持在这里和这里合并。
Windows 8另外还有一个函数SetCoalescableTimer ,它支持根据MSDN进行合并。

所以在Windows 7和Windows 8中有很多关于定时器合并的话题。但是看起来它可能已经在早些时候被实现了。 是这样吗?

首先, 自Vista以来可用的SetThreadpoolTimer在Vista下提供了定时器合并 。 还是它只提供接口,并且实际上只有在Windows 7以后才实现合并?
从“线程池定时器和I / O”我可以读取

“这实际上是一个影响能源效率的function,有助于降低整体功耗,它基于一种称为定时器合并的技术。”

对于支持SetThreadpoolTimer函数的所有Windows版本,这句话是否正确?

其次,现在我开始怀疑了。 我可以看到timeSetEvent可用,因为XP具有名为uResolution参数。 在定时器事件等待期间,这个参数是否像timeBeginPeriod一样改变全局定时器的分辨率,还是只影响这个特定的定时器,还提供定时器合并

最后,在Windows XP或Vista下是否还有其他function可以提供定时器合并?

Solutions Collecting From Web of "计时器在Windows 7之前合并"

总的来说几句话:

定时器合并提供了一种减少中断数量的方法。 允许应用程序为其时间要求指定容差。 这允许操作系统“批量”中断,带来一些后果:

  • 中断的数量可能会减少。 (+)
  • 上下文切换的次数可能会更少。 (+)
  • 功耗可能会降低。 (+)
  • 大量的操作可能必须在这些成批的中断( – )上完成
  • 调度程序可能不得不在此时调度大量进程( – )
  • 时间分辨率更差( – )

Windows以及其他基于中断的操作系统总是“批量”定时事件。 任何在特定时间发生的事情都要依靠到期时间到期。 因此,事件与中断相结合。 这个方案的粒度由中断频率决定。 必须阅读那些对计时器合并感兴趣的人: MSDN:Windows计时器合并 。

出于性能的原因,应尽一切努力尽可能减少中断的数量。 不幸的是,很多软件包timeBeginPeriod系统定时器分辨率设置得非常高,例如通过多媒体定时器界面timeBeginPeriod / timeEndPeriod或底层API NtSetTimerResolution 。 就像Hans提到的那样:“Chrome”就是一个很好的例子,说明这些功能的使用如何被夸大。


其次,现在我开始怀疑… timeSetEvent是多媒体计时器功能之一。 它在引擎盖下使用了timeBeginPeriod

它使用得很糟糕:它将系统定时器分辨率设置为与uResolution一样好,就像在执行平台上提供的定时器分辨率一样。 在较大的uDelay值时,它可能会以低分辨率等待,直到接近延迟期限,然后才提高系统定时器分辨率,但会将整个等待时间段的定时器分辨率设置为指定的uResolution 。 这是痛苦的,知道高分辨率也适用于长时间的延迟。 但是,多媒体计时器功能不被建议用于大的延迟。 但是一遍又一遍地设置分辨率也不好(见下面的注释)。

关于timeSetEvent总结:这个函数根本就没有做任何事情,比如合并,反之亦然:它可以增加中断的数量; 从这个意义上讲,它将事件分散到更多的中断,它将它们“拆分”。

SetThreadpoolTimer引入了“批处理”事件的思想。 由于对Windows笔记本电脑的电池续航时间的投诉日益增多,这个主要原因被迫。 SetWaitableTimerEx进一步推动了这个策略,并且SetCoalescableTimer是最近访问合并定时器的API。 后者引入了值得考虑的TIMERV_DEFAULT_COALESCING和TIMERV_NO_COALESCING,因为它们允许忽略某些事实。


借此机会了解系统定时器分辨率的一些注意事项:

改变系统定时器的分辨率,不仅仅是提高了中断频率。 与使用timeBeginPeriod / NtSetTimerResolution一起的一些效果:

  1. 中断频率改变
  2. 线程量子变化(线程时间片)(!)
  3. 打嗝的系统时间( MSDN:“…频繁的电话会显着影响系统时钟” )
  4. 打开系统时间调整时打嗝( SetSystemTimeAdjustment

第3点被部分照顾与Windows 7和第4点只能解决与Windows 8.1。 系统时间的打嗝可能与支持的最小定时器分辨率(典型系统上的15.625 ms)一样大,并且在经常使用timeBeginPeriod / NtSetTimerResolution时累积。 尝试调整系统时间以匹配NTP参考时,这可能会导致相当大的跳跃。 NTP客户端需要以较高的定时器分辨率运行,以在Windows版本<Windows 8上运行时获得合理的准确性。

最后: Windows自己改变系统计时器的分辨率,只要它看到优势。 支持的定时器分辨率数量取决于底层硬件和Windows版本。 通过调用timeBeginPeriod随着周期的增加,然后调用timeBeginPeriod ,可以获得可用分辨率的列表。 某些受支持的解决方案可能在特定平台上被Windows“不喜欢”,并被修改以更好地适应Windows需求。 例如:在某些平台上,XP可能会在短时间内将“用户设置”分辨率更改为〜4ms。 特定Windows版本<8.1确实会在不可预知的时间更改计时器分辨率。

如果要求应用程序完全独立于这些文物,则必须自行获得最高的可用分辨率。 这样,应用程序支配整个系统的分辨率,而不必担心其他应用程序或操作系统更改定时器分辨率。 更现代的平台确实支持0.5ms的定时器分辨率。 timeBeginPeriod不允许获取这个分辨率,但是NtSetTimerResolution可以。 在这里我描述了如何使用NtSetTimerResolution获得0.5毫秒的分辨率。

在这样的条件下,功耗可能会增加,但这是可靠分辨率支付的费用:在现代硬件上,上下文切换的能源成本通常为0.05 mJ至0.2 mJ(有人估计每年的全局上下文切换总量? )。 Windows将线程量(时间片)削减到约。 2/3时定时器分辨率设为最大。 随之,功耗提高了大约 30%!