泰晓科技 -- 聚焦 Linux - 追本溯源,见微知著!

随身Linux Lab实验盘:128G可当256G使

LWN 138969: 动态时钟(dynamic tick)补丁

Wang Chen 创作于 2018/06/22

原文:The dynamic tick patch 原创:By corbet @ June 7, 2005 翻译:By unicornx of TinyLab.org 校对:By guojian-at-wowo

The timer interrupt is one of the most predictable events on a Linux system. Like a heartbeat, it pokes the kernel every so often (about every 1ms on most systems), enabling the kernel to note the passage of time, run internal timers, etc. Most of the time, the timer interrupt handler just does its job and nobody really notices.

定时器中断是 Linux 系统上最可预期的(predictable)事件之一(译者注:dynamic tick 之前都是 periodic tick,因此 timer interrupt 会周期性地产生)。 像心跳一样,该中断周期性地发生(在大多数系统上大约每隔 1ms 发生一次),内核从而能够感受到时间的流逝,并且据此运行内部的定时器等。但大多数情况下,定时器中断处理程序只是在默默地执行它自己的工作,很少有人会真正注意到它的存在。

There are times, however, when this interrupt can be unwelcome. Many processors, when idle, can go into a low-power state until some work comes along. To such processors, the timer interrupt looks like work. If there is nothing which actually needs to be done, however, then the processor might be powering up 1000 times per second for no real purpose. Timer interrupts can also be an issue on virtualized systems; if a system is hosting dozens of Linux instances simultaneously, the combined load from each instance’s timer interrupt can add up to a substantial amount of work. So it has often been thought that there would be a benefit to turning off the timer interrupt when there is nothing for the system to do.

然而,有时候这种中断可能并不受欢迎。 许多类型的处理器在系统空闲时可以进入低功耗状态,直到出现新的任务需要处理才会恢复正常工作状态。对于这类情况,定时器中断看起来更像是额外的负担。因为在这种情况下,即使没有什么实际的工作要做,处理器也会在一秒中被唤醒 1000 次。 有时候定时器中断对于虚拟化系统也是一个问题;如果一个主机系统上同时运行着数十个 Linux 虚拟机实例,则来自每个实例的定时器中断处理累加起来对主机也是不小的负担。所以大家认为,当系统没有实际计算任务时,关闭定时器中断会带来好处。

Tony Lindgren’s dynamic tick patch is another attempt to put a lid on the timer interrupt. This version of the patch only works on the i386 architecture, but it is simple enough that porting it to other platforms should not be particularly difficult.

Tony Lindgren 所带来的动态时钟(dynamic tick)补丁 是又一次对定时器中断进行优化的有益尝试。 目前该补丁只适用于 i386 架构,但它很简单,将其移植到其他平台应该不是什么难事。

The core of the patch is a hook into the architecture-specific cpu_idle() function. If a processor has run out of work and is about to go idle, it first makes a call to dyn_tick_reprogram_timer(). That function checks to see whether all other processors on the system are idle; if at least one processor remains busy, the timer interrupt continues as always. Experience has shown that trying to play games with the timer interrupt while the system is loaded leads to a net loss in performance - the overhead of reprogramming the clock outweighs the savings. So, if the system is working, no changes are made to the timer.

该补丁的核心修改是在特定于体系架构的 cpu_idle() 函数中添加了一个钩子。具体操作是针对一个处理器,在其即将进入空闲状态之前,先调用 dyn_tick_reprogram_timer()。 该函数会检查系统上其他所有处理器是否已经处于空闲状态;如果还存在其他处理器处于忙碌态,则定时器中断将正常触发,维持不变。经验表明,在系统非空闲时试图修改定时器中断的设置只会导致整体性能的净损失,因为重新对时钟源编程的开销超过了其节省的部分。因此,只要系统还在忙碌,就不会更改定时器。

If, instead, all CPUs on the system are idle, there may be an opportunity to shut down the timer interrupt for a while. When the system goes idle, there are only two events which can create new work to do: the completion of an I/O operation or the expiration of an internal kernel timer. The dynamic tick code looks at when the next internal timer is set to go off, and figures it might be able to get away with turning off the hardware timer interrupt until then. After applying some tests (there are minimum and maximum allowable numbers of interrupts to skip), the code reprograms the hardware clock to interrupt after this time period, and puts the processor to sleep.

反之,如果系统中的所有 CPU 都处于空闲状态,则还是有机会在一段时间内关闭定时器中断从而达到节省能耗的目的。一般来说当系统空闲时,仅有两种事件可能会唤醒系统重新投入运行:一种是输入输出操作完成引起的中断信号事件,另一种是内部内核定时器到期事件。动态时钟的代码会检查下一个内部定时器到期的时间,从而计算得到可以关闭硬件定时器中断的最大时长。再经过内部的有效范围检查(确保休眠的时间在允许的最小和最大值之间)后,代码重新编程设定硬件时钟下一次产生中断的时间,然后处理器就可以进入休眠态了。

At some point in the future, an interrupt will come along and wake the processor. It might be the clock interrupt which had been requested before, or it could be some other device - a keyboard or network interface, for example. The dynamic tick code hooks into the main interrupt handler, causing its own handler to be invoked for every interrupt on the system, regardless of source. This code will figure out how many clock interrupts were actually skipped, then loop calling do_timer_interrupt() until it catches up with the current time. Finally, the interrupt handler restores the regular timer interrupt, and the system continues as usual.

在未来的某个时刻,会有一个中断到来并唤醒处理器。它可能是之前请求的时钟中断,或者可能是来自其他设备的中断,例如键盘或网络接口。动态时钟的补丁在中断处理主逻辑中增加了相关的处理代码。这样无论中断来自哪里,动态时钟的处理都会被调用。动态时钟的代码会计算出休眠期间实际经过了多少个时钟中断,然后循环调用 do_timer_interrupt(),对缺失的时间部分进行补足,直到和当前时间持平。最后,中断处理程序恢复常规定时器中断,至此系统就像往常一样继续运行。

The end result is a system which can drop down to about 6 timer interrupts per second when nothing is going on. That should eventually translate into welcome news for laptop users and virtual hosters running Linux.

从测试的结果来看(译者注,启用动态时钟后),当系统空闲时,每秒钟发生的定时器中断可以下降到大约只有 6 次。这对于那些在笔记本电脑上或者虚拟机环境里运行 Linux 的用户来说不啻是个好消息。

Read Album:

Read Related:

Read Latest: