创作者 | Frederic Weisbecker
方案策划 | 闫园园
SUSE Labs 精英团队探寻了 Kernel CPU 防护以及主要部件之一:Full Dynticks(或 Nohz Full),并编写了本系列产品文章内容:
CPU 防护 – 介绍
CPU 防护 – Full Dynticks 深探
CPU 隔离 – Nohz_full
CPU 防护 – 管理方法和衡量
CPU 防护 – 实践活动
文中是第二篇。
大家以前详细介绍了 linux kernel 计时器中断,及其它在 kernel 内部结构状态和服务项目维护保养中饰演的人物角色。颤动比较敏感型工作中载荷的客户很有可能期待解决这类高速传输事情造成的 CPU 周期时间盗取和 CPU 缓存文件消除。
殊不知,终止计时器中断并非易事,由于很多 kernel 部件依靠规律性事情,主要是计时器、按时和调度程序流程。但有一个除外:当 CPU 空闲时,不用这类 100~1000 Hz 頻率的中断。实际上,当 CPU 不用工作中时,就沒有每日任务调度器必须维护保养,沒有计时器排长队,都没有按时客户。
因而,“环保节能”当然变成摆脱规律性计时器的第一个发病原因,因为它是针对 CPU 空闲状态的提升。CONFIG_NO_HZ_IDLE(https://lwn.net/Articles/223185/)内核选择项产生了一种终止规律性中断的体制,并在 CPU 空闲状态时完成。这一重大突破为达到颤动比较敏感型工作中载荷的要求平整了路面,并带来了一个动态性中断的基础架构。下面便是拓展这一作用,便于在 CPU 繁忙的情况下,还可以终止时钟中断。殊不知,现阶段的技术实力并无法做到大家期望的总体目标,下一节中讲解的每一个问题都花了两年時间来处理。
时钟中断服务项目的取代计划方案
如前文上述,按时的一次性事情(记时器调整)或规律性事情(调度程序流程、记时、RCU 等)的好多个分系统必须时钟中断 。因而,如果我们想在 CPU 运作具体每日任务时终止时钟中断,则不可以忽视这些要求事情。大家务必应用取代计划方案为他们给予服务项目,或是在最坏的情形下限定大家的服务项目。换句话说,针对这种分系统对规律性时钟中断的依赖感,大家务必从下列各种各样方法中挑选什么是有可能且相应的:
关联到另一个 CPU
有一些工作中碰巧在现阶段 CPU Tick 时实行,但它也能够在另一个 CPU 上实行,而并不会发生一切问题。未关联的记时器就这样的状况,即未固定不动到一切 CPU 的记时器。这也间接性适用未关联的延迟时间工作中序列(https://www.kernel.org/doc/html/v4.10/core-api/workqueue.html),由于他们依靠未关联的记时器。这种记时器非常容易关联到别的地区,但这也是以运作这种未关联工作中的 CPU 资金投入一些附加花销为结果的。
负荷到另一个 CPU
Some tick work related to the current CPU is not initially designed to be executed on another CPU but we can manage to do it, usually at some cost. This is the case for RCU callbacks processing and regular scheduler tick. 有一些与现阶段 CPU 有关的时钟中断,其起初设计方案并不是是在另一个 CPU 上实行的,但我们可以想方设法保证这一点,这通常必须投入一定的成本费。RCU 调整解决和基本调度程序流程便是这样的事情。
RCU 调整解决
RCU(https://lwn.net/Articles/262464/)是一种无锁同歩体制,一旦确保全部 CPU 都能见到特定的升级,载入程序流程就可以实行调整。这种调整通常在其排长队的 CPU 上实行,即可以来源于 softirq 前后文,还可以来源于名叫“rcuc”的固定不动内核进程。追踪和实行这种调整必须时钟中断以轮询他们的序列和内部结构状态。
为了更好地彻底解决这个问题,一项名叫 RCU NOCB 的作用,根据配备内核主要参数 CONFIG_RCU_NOCB_CPU=y 得到完成。它容许将所有工作中从依靠自始至终中断迁移到一组名叫“rcuog, rcuop or rcuos”的未关联的 CPU 的内核进程。
这当然了会给运作 rcuo[gps]kthreads 和锁住市场竞争的 CPU 产生相应的花销。
调度程序流程时的时钟中断
调度器必须不断搜集有关当地和全局性每日任务负荷的多种统计数据,进而使其内部结构状态维持全新。在非常长的時间内,繁忙的 CPU 在进到彻底 nohz 方式以前很有可能有残留的 1 Hz Tick。最后,这种残留的 1 Hz Tick 会迁移到未关联的工作中序列中。
这也会给运作这种工作中序列的 CPU 产生大量花销。
用前后文变更事情更换轮询事情
记时器中断从中断的语义和頻率推论信息内容。这也是“CPU 做账”和“RCU 静态数据状态汇报”2个主要部件的基本。为了更好地在沒有中断的情形下解决这种特点,大家必须从前后文转变和时间格式(通常要一定成本)中推论出这种信息内容。这读起來很有可能很抽象化,因而,最好是在日常生活中多了解一下。
Cputime 做账
当在 procfs 系统文件中查验特定过程的 stat 文档时(/proc/$PID/stat : https://man7.org/linux/man-pages/man5/procfs.5.html),可以查找好几个前后文的 cputime 统计数据,例如进程在使用者室内空间、内核空间、远程服务器等中耗费的時间。
这种数据由调度程序流程 cputime 做账作用来维护保养。Tick 会开启并查验它中断了哪个前后文。假如中断了客户前后文,则一个 jiffy(2次 Tick 中间的時间)将记入客户時间。假如中断了内核前后文,则 jiffy 将被记入内核時间。这种做法如下图所示:
图 3:Dynticks- 空闲 Cputime 做账
在上例中,大家纪录了 2 次客户 Tick 和 6 次内核 Tick。针对 1000 Hz 的 Tick,一个 jiffy 相当于 1 ms。因而,客户时间记录为 2ms,内核时间记录为 6ms。最后結果经常与在每一种自然环境中的具体時间相仿,但通常早已非常好啦。Tick 頻率越高,cputime 越精准。
如今检查一下闲置不用做账。这类方法不一样,由于空闲時间内沒有 Tick,因而,大家能够做的便是测算撤出空闲状态和进到空闲状态的时间格式中间的差。
为了更好地可以在运作非空闲每日任务而且 Tick 终止时对客户和内核 CPU 使用时间开展做账,大家一定要将空闲做账逻辑性拓展到客户 / 内核做账中。如下所示所显示:
图 4:Full dynticks Cputime 做账
在这儿,内核時间可以根据客户进到空闲状态的时间格式减掉明确提出空闲状态的时间格式来查找。与此同时,在 idle_enter 以前和 user_exit 以后产生的一切事都需要加之中。客户时间是用户进到和客户撤出空闲状态中间的差,它的测算比较简单,乃至比根据 Tick 的做账更为精准。
但这提供了一个问题:为什么没有在 Tick 运作时一直应用这类解决方法呢?
由于每一次在大家超越客户 / 内核界限时,必须载入精准但很有可能获取比较慢的硬件配置时钟。通用性工作中负荷常常碰到这样的事情,进而造成特性损害。因而,这类无 Tick 的做账务必保存给将其内容在内核的工作负荷。
RCU 静止不动状态汇报
当 RCU 写者程序流程公布升级并将调整排长队等候实行时,它务必等候全部 CPU 汇报新的“RCU 静止不动状态”。这代表着 CPU 早已经过了不属于受维护 RCU 阅读者程序流程的编码,称之为“RCU 载入端临界区”。
事实上,rcu_read_lock() 和 rcu_read_unlock() 中间的所有编码(或一切不能占领的编码)全是“RCU 载入端临界区”;别的剩余的全是“RCU 静止不动状态”。
要跟踪静止不动状态,RCU 依靠 Tick 并查验它中断了哪个前后文。假如中断了没有在 rcu_read_lock()/rcu_read_unlock() 对维护一部分内的编码,它汇报静止不动状态。假如中断了客户室内空间,它也被觉得是静止不动状态,由于客户室内空间不可以应用内核 RCU 分系统。
图 5:Dynticks- 空闲 RCU 静止不动状态汇报
图中还表明了 tick-deprived idle 每日任务怎样从独特处理方法中再度获益。空闲 CPU 并不是积极汇报静止不动状态,反而是利用进到“RCU 拓展静止不动状态”处于被动汇报。它在进到和撤出空闲状态时增长一个具备详细内存屏障的分子自变量。
随后,等候全部 CPU 汇报静态数据状态的 RCU 最后会扫描仪未响应的 CPU,以找到拓展的静态数据状态,并意味着这种 CPU 汇报静态数据状态。
这类方式往往合理,是由于我们知道空闲前后文不应用 RCU。我们知道客户室内空间具备同样的特性,因而,当运作非空闲每日任务的情况下终止 Tick 时,这类处于被动汇报计划方案可以扩大到客户室内空间中:
图 6:Full-dynticks RCU 静止不动状态汇报
因为 CPU 非常少在内核中耗费很多時间,因而,以上建议将替代根据 Tick 的静止不动状态汇报。RCU 拓展的静止不动状态要不在期间发生短暂性的延迟时间,要不就不断很长期。
与 cputime 做账相近,这一样有一个问题:为什么即使在 Tick 运作时都不选用这类方式?
由于这将在各个客户 / 内核来回全过程中造成一个成本昂贵的原子操作,而且会有一个完善的内存屏障。除此之外,汇报静态数据状态的义务最后由别的 CPU 担负。
要是没有别的挑选,则再次应用 Tick
要是没有规律性事情或是经常事情,有一些状况没办法处理。例如,调度程序流程每日任务占领便是如此。为了确保当地公平公正,调度程序流程务必能在多每日任务中间共享资源 CPU,并定期维护是不是必须占领。因而,在 CPU 上运作单独每日任务是在空闲前后文中进一步停止 Tick 的要求。其他子系统也可能会请求定期 Tick,从而在某些情况下保持运行:posix cpu 计时器、perf 事件等。我们将进一步探讨这些细节。
您可以看到,在运行实际任务时,完全停止 Tick 是可能的,但会出现很多陷阱,用户必须准备做好一些权衡。我们将在下一篇文章中详细解释。