Alibaba Cloud Linux 2从内核版本kernel-4.19.91-24.al7开始支持Group Identity功能,您可以通过该功能为每一个CPU cgroup设置不同的身份标识,以区分不同CPU cgroup中进程任务的优先级。

背景信息

在业务的混合部署(延迟敏感型和计算型任务混合部署在同一台实例)场景中,Linux内核调度器需要为高优先级任务赋予更多的调度机会以最小化调度延迟,并需要把低优先级任务对内核调度带来的影响降到最低。基于该场景,Alibaba Cloud Linux 2提供了Group Identity功能,为CPU cgroup新增了配置调度优先级的接口,且不同优先级的任务具有以下特点:
  • 高优先级任务的唤醒延迟最小化。
  • 低优先级任务不对高优先级任务造成性能影响。主要体现在:
    • 低优先级任务的唤醒不会对高优先级任务造成性能影响。
    • 低优先级任务不会通过SMT调度器共享硬件unit而对高优先级任务造成性能影响。

功能原理

Group Identity功能可以对每一个CPU cgroup设置身份标识,以区分cgroup中的任务优先级。Group Identity核心是双红黑树设计,在CFS(Completely Fair Scheduler)调度队列的单红黑树基础上,新增了一颗低优先级的红黑树,用于存放低优先级任务。

系统内核在调度包含具有身份标识的任务时,会根据不同的优先级做相应处理。具体说明如下表:
身份标识(按优先级由高到低排序) 说明
ID_HIGHCLASS 高优先级任务,相较于低于其优先级的任务会有更多的资源抢占机会。
CFS调度器在调度高优先级任务时,会有以下行为的变化:
  • 如果当前运行的是低优先级任务,当高优先级任务被唤醒时,可无条件进行资源抢占。
  • 如果当前运行的是普通优先级任务,当高优先级任务被唤醒时vruntime小于普通优先级任务,则高优先级任务可以无视原有调度策略(任务在CPU上运行的时间小于最小运行时间时不可以进行资源抢占),进行资源抢占。
  • 在排队运行任务的场景中,如果当前运行的是普通或低优先级的任务,当高优先级任务的vruntime小于当前任务时,高优先级任务可以无视原有调度策略(任务在CPU上运行的时间小于最小运行时间时不可以进行资源抢占),进行资源抢占。
ID_NORMAL 普通优先级任务,相较于低于其优先级的任务会有更多的资源抢占机会。
CFS调度器在调度普通优先级任务时,会有以下行为的变化:
  • 如果当前运行的是低优先级任务,当普通优先级任务被唤醒时,可无条件进行资源抢占。
  • 在排队运行任务的场景中,如果当前运行的是低优先级任务,当普通优先级任务vruntime小于低优先级任务时,普通优先级任务可以无视原有调度策略(任务在CPU上运行的时间小于最小运行时间时不可以进行资源抢占),进行资源抢占。
ID_UNDERCLASS 低优先级任务。

CFS调度器在调度低优先级任务时,会有以下行为的变化:

如果对端的SMT调度器运行了SMT驱逐者(ID_SMT_EXPELLER)任务,则低优先级任务无法被调度至CPU上,即等同于被踢出了任务运行队列。

以上身份标识的作用范围遵从CPU cgroup的资源管理策略:
  • 在同一层级的cgroup中的任务,身份标识的优先级生效。
  • 相对于父层级的cgroup,任务身份标识的优先级不生效;相对于子层级的cgroup,任务身份标识的优先级生效。
  • 同优先级的身份标识之间的资源竞争基本服从CFS调度器的策略,但需要注意ID_UNDERCLASSID_NORMAL身份标识的任务没有最小运行时间的保障。
其他身份标识说明:
身份标识 说明
ID_SMT_EXPELLER SMT驱逐者,其作用为SMT调度器运行时,驱逐SMT对端CPU上的ID_UNDERCLASS身份标识的任务。
ID_IDLE_SEEKER 表示当任务被唤醒时,会在调度器策略范围内最大限度的尝试找到空闲CPU(Idle CPU)。
ID_IDLE_SAVER 与内核参数sched_idle_saver_wmark结合使用,您可以通过sched_idle_saver_wmark自行配置空闲时长水位线。当ID_IDLE_SAVER身份标识的任务被唤醒时,只会尝试找到高于该水位线的空闲CPU,不会尝试找到低于该水位线的空闲CPU。

接口说明

  • 身份标识配置接口
    Group Identity提供了两个用于设置任务身份标识的接口:/sys/fs/cgroup/cpu/$cg/cpu.identity/sys/fs/cgroup/cpu/$cg/cpu.bvt_warp_ns。其中变量$cg表示任务实际所在的子cgroup目录节点。在使用身份标识配置接口前,您需要注意:
    • cpu.identity接口的配置会覆盖cpu.bvt_warp_ns接口的配置。
    • 您只需要使用任一接口设置任务的身份标识,不建议同时设置两个接口。
    • 如果您不熟悉操作系统内核的相关操作,不建议使用cpu.identity接口。
    接口说明如下:
    接口 说明
    cpu.identity 默认取值为0,表示身份标识为ID_UNDERCLASS。该接口的取值说明如下:
    • 0:表示身份标识ID_UNDERCLASS
    • 1:表示身份标识ID_HIGHCLASS
    • 2:表示身份标识ID_SMT_EXPELLER
    • 3:表示身份标识ID_IDLE_SAVER
    • 4:表示身份标识ID_IDLE_SEEKER
    • 空值:表示身份标识ID_NORMAL
    cpu.bvt_warp_ns 默认取值为0,表示身份标识为ID_NORMAL。该接口的取值说明如下:
    • 2:表示同时具有身份标识ID_SMT_EXPELLERID_IDLE_SEEKERID_HIGHCLASS
    • 1:表示同时具有身份标识ID_HIGHCLASSID_IDLE_SEEKER
    • 0:表示身份标识ID_NORMAL
    • -1:表示同时具有身份标识ID_UNDERCLASSID_IDLE_SAVER
  • 调度特性开关配置接口
    运行以下命令,您可以通过sched_features接口查看到内核调度特性的默认配置。
    cat /sys/kernel/debug/sched_features
    具体说明如下:
    调度特性 说明 默认值
    ID_IDLE_AVG 该特性与ID_IDLE_SAVER身份标识配合,把ID_UNDERCLASS任务的运行时间计入空闲时长,防止只有ID_UNDERCLASS任务运行时仍保留空闲CPU(Idle CPU)的问题,避免资源浪费。 ID_IDLE_AVG:表示特性为启用状态。
    ID_RESCUE_EXPELLEE 该特性作用于负载均衡场景,如果任务无法找到可用的CPU资源,则正在进行驱逐ID_UNDERCLASS任务的CPU会成为负载均衡的目标。用于帮助ID_UNDERCLASS任务尽快摆脱被驱逐的状态。 ID_RESCUE_EXPELLEE:表示特性为启用状态。
    ID_EXPELLEE_NEVER_HOT 该特性被启用后,正在被驱逐的任务在判断是否需要迁移至其他CPU时,不会因为热缓存的原因而造成拒绝迁移。用于帮助ID_UNDERCLASS任务尽快摆脱被驱逐的状态。 NO_ID_EXPELLEE_NEVER_HOT:表示特性为关闭状态。
    ID_LOOSE_EXPEL 该特性被启用后,CPU不会在每次选择任务时更新驱逐状态,而是根据内核参数sched_expel_update_interval设置的时间自动更新。该特性的开关仅影响CPU选择任务时的状态更新,不影响处理IPI中断的更新。 NO_ID_LOOSE_EXPEL:表示特性为关闭状态。
    ID_LAST_HIGHCLASS_STAY 该特性被启用后,CPU上最后一个运行的ID_HIGHCLASS任务不会被迁移至其他CPU上。 ID_LAST_HIGHCLASS_STAY:表示特性为启用状态。
  • 用于sysctl配置内核参数的接口
    Group Identity的部分功能的实现需要以内核参数的取值作为参考。相关内核参数的具体说明如下表:
    内核参数 说明 单位 默认值
    /proc/sys/kernel/sched_expel_update_interval CPU在选择任务时,驱逐状态的自动更新时间间隔。仅在ID_LOOSE_EXPEL特性开启时生效。 ms 10
    /proc/sys/kernel/sched_expel_idle_balance_delay CPU在驱逐状态下,idle balance的最小时间间隔。取值为-1时表示不允许进行idle balance

    当CPU上均为ID_UNDERCLASS任务且任务在被驱逐时,CPU的状态可以理解为空闲状态,在该状态下CPU会进行idle balance以提高负载均衡的效果,但会对ID_UNDERCLASS任务造成损伤。通过设置sched_expel_idle_balance_delay参数可以缓解该问题。

    ms -1
    /proc/sys/kernel/sched_idle_saver_wmark 设置CPU空闲时间的水位线。当ID_IDLE_SAVER任务被唤醒时,只会尝试找到高于该水位线的空闲CPU,不会尝试找到低于该水位线的空闲CPU。 ns 0

信息输出说明

在使用Group Identity功能期间,您可以运行以下命令,查看多维度的参数信息。
cat /proc/sched_debug
输出的参数说明如下:
参数 说明
nr_high_running 当前CPU上运行的ID_HIGHCLASS任务数量。
nr_under_running 当前CPU上运行的ID_UNDERCLASS任务数量。
nr_expel_immune 当前CPU上运行的非ID_UNDERCLASS任务数量。
smt_expeller 当前CPU是否有ID_SMT_EXPELLER任务在运行。参数值为1表示有;参数值为0表示无。
on_expel SMT调度器的对端是否有ID_SMT_EXPELLER任务在运行。参数值为1表示有;参数值为0表示无。
high_exec_sum 当前CPU上ID_HIGHCLASS任务的累计运行时间。
under_exec_sum 当前CPU上ID_UNDERCLASS任务的累计运行时间。
h_nr_expel_immune 当前cfs_rq上运行的非ID_UNDERCLASS任务数量。
expel_start CPU在驱逐任务的开始阶段,两个红黑树结构的最小虚拟运行时间的差距。
expel_spread 由于CPU驱逐状态造成的两个红黑树结构最小虚拟运行时间的累计差距。
min_under_vruntime 低优先级红黑树结构的最小虚拟运行时间。