Linux 6.9内核对CPU计时器代码进行了大量修改,这已经酝酿了多年,并且具有一些功率和性能优势。
Thomas Gleixner在Linux6.9合并窗口的计时器/核心拉取请求中总结了这一重大的分层计时器模型更新。他很好地解释了这一重大任务:
分层定时器拉模型
当定时器轮定时器被武装时,它们被放置到CPU的定时器轮中,而CPU在到期时很可能会很忙。这样做是为了避免在可能空闲的CPU上唤醒。
这在几个方面是错误的:
1)根据定义,选择目标CPU的启发式方法是错误的,因为正确预测的机会接近于零。
2)由于#1,定时器可能累积在单个目标CPU上
3)入队路径中所需的计算只是可疑值的开销,特别是在考虑到绝大多数计时器定时器在到期之前被取消或重新武装的情况下。
计时器拉取模型通过删除入队上的目标计算,并将计时器始终放在准备好计时器的CPU上来避免上述问题。
这是通过为CPU固定定时器和全局定时器提供单独的轮子来实现的,这些定时器并不关心它们在哪里到期。
只要CPU处于繁忙状态,它就处理在CPU本地计时器轮上排队的固定计时器和全局计时器。
当CPU空闲时,它会评估自己的计时器轮:
- 如果第一个到期计时器是固定计时器,则可以忽略全局计时器,因为CPU将在它们到期之前唤醒。
- 如果第一个到期计时器是全局计时器,则该到期时间被传播到计时器拉取层次结构中,CPU确保在第一个固定计时器时唤醒。
定时器拉式层次结构在最低层以8个为一组的CPU进行组织,在下一层以8个为一组的CPU进行组织,直到不需要进一步的组聚合为止,即层数为log 8(NR_CPUS)。8这个神奇数字是通过实验确定的,但如果需要可以调整。
在每个组中,一个繁忙的CPU充当迁移器。只有一个CPU可以避免远程计时器轮上的锁争用。
Migrator CPU检查它自己的定时器轮,处理组中是否有其他CPU已经空闲,并且全局定时器即将到期。如果有全局计时器要超时,则Migrator锁定远程CPU计时器轮并处理超时。
根据层次结构中的组级别,此处理可能需要将层次结构向下遍历到CPU级别。
当最后一个CPU空闲时要特别小心。此时,CPU是层次结构顶部的系统范围迁移器,因此它不能委托给层次结构。它需要武装自己的计时器设备,以便在层次结构中的第一个到期计时器或在第一个CPU本地计时器处到期,后者总是先到期。
这完全消除了排队路径的开销,例如,用于网络连接真正的热路径,并将其交易为稍微复杂的空闲路径。
Gleixner接着解释了这一大努力的好处:
这已经开发了几年,最终的系列已经由来自硅片供应商的不同团队进行了广泛的测试,并通过了广泛的CI。
在以网络为中心的工作负载上观察到了轻微的性能改善,英特尔团队证实,这允许他们在大多数空闲的情况下首次完全关闭多芯片插槽上的芯片。
目前正在调查的特定过载netperf测试中,只有一个突出的~1.5%的回归,但其余的回归要么是积极的,要么是中性的,要么是电源管理方面的积极的。
这 定时器拉 was merged alongside all of the other TIP.git material for the Linux 6.9 merge window. It will be fun to fire up some benchmarks soon of Linux 6.9 to see how the performance and power is looking overall given the numerous feature changes this cycle.