1

在 Windows 7 和 Windows 8 中有计时器合并支持,例如:Timer coalescing in .net
Windows 7 有一个功能SetWaitableTimerEx,据称它支持此处此处的合并。 根据 MSDN,
Windows 8 还具有支持合并的功能。SetCoalescableTimer


很多关于 Windows 7 和 Windows 8 中的计时器合并的讨论。但是看起来它可能已经更早地实现了。是这样吗?


首先,SetThreadpoolTimer由于Vista在Vista下提供了定时器合并,是否可用。还是它只提供接口,实际上只在 Windows 7 之后才实现合并?
“线程池计时器和 I/O”我可以读到

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

这句话对所有支持SetThreadpoolTimer功能的 Windows 版本都正确吗?


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


最后,在 Windows XP 或 Vista 下是否有任何附加或替代功能可以提供定时器合并?

4

1 回答 1

4

总的说几句:

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

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

Windows 以及其他基于中断的操作系统总是“批处理”定时事件。任何设置为在特定时间发生的事情都依赖于中断到期的到期时间。因此,事件与中断合并。该方案的粒度由中断频率决定。对计时器合并感兴趣的人必须阅读:MSDN:Windows 计时器合并

出于性能原因,应尽一切努力尽可能减少中断的数量。不幸的是,许多软件包确实将系统计时器分辨率设置得非常高,例如通过多媒体计时器接口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 点仅在 Window 8.1 中得到解决。系统时间的中断可能与支持的最小计时器分辨率(典型系统上为 15.625 毫秒)一样大,并且它们在何时timeBeginPeriod/NtSetTimerResolution频繁地累积。当尝试调整系统时间以匹配 NTP 参考时,这可能会导致相当大的跳跃。在 Windows 版本 < Windows 8 上运行时,NTP 客户端需要以高计时器分辨率运行以获得合理的准确性。

最后:只要 Windows 看到这样做的好处,它就会更改系统计时器的分辨率。支持的计时器分辨率的数量取决于底层硬件和 Windows 版本。可用分辨率的列表可以通过扫描它们来获得,方法是调用timeBeginPeriod增加周期,然后调用NtQueryTimerResolution。Windows 在特定平台上可能“不喜欢”某些受支持的分辨率,并对其进行修改以更好地满足 Windows 需求。示例:XP 可能会在某些平台上短时间后将大约 4 毫秒的“用户设置”分辨率更改为 1 毫秒。特定的 Windows 版本 < 8.1 确实会在不可预测的时间更改计时器分辨率。

如果要求应用程序完全独立于这些人工制品,则它必须自行获得最高可用分辨率。这样,应用程序就控制了系统范围的分辨率,并且不必担心其他应用程序或操作系统更改计时器分辨率。更现代的平台确实支持 0.5 毫秒的计时器分辨率。timeBeginPeriod不允许获取此分辨率,但NtSetTimerResolution可以。在这里,我描述了如何使用 NtSetTimerResolution 来获得 0.5 毫秒的分辨率。

在这种情况下,功耗可能会增加,但这是为可靠分辨率支付的费用:在现代硬件上,上下文切换的能量成本通常为 0.05 mJ 到 0.2 mJ(有没有人估计全球每年的上下文切换总量? )。Windows 将线程量子(时间片)削减到大约。定时器分辨率设置为最大值时的 2/3。结果,功耗增加了大约。30%!

于 2014-05-16T13:25:59.860 回答