1. 参考文档
  1. openEuler21.09内核代码

根据openEuler官网上的介绍,其内核对进程调度的负载均衡做了算法优化,来提升系统性能。我们就来看看代码到底优化了什么。

注:下面所涉及的修改不一定都是huawei提交的,有些是从Linux主线上游拉下来的。根据openEuler内核源码看,应该是基于Linux5.10版本。

2. 代码分析

openEuler进程调度优化主要点:优化进程负载均衡算法,减少负载均衡过程中的开销,提升性能;通过对比分析代码,主要分几下个点:

2.1 sched_slice()函数

​ 1)nr_running是个粗略估算,当考虑cgroups时,就明显有缺陷了,需要用h_nr_running来反映组调度中的队列数量;

​ 2)cgroups计算slice容易引起over-scheduling,所以需要比较下slice和sched_min_granularity的值;

请添加图片描述
(图左边是openEuler内核,右边是Linux5.10内核)

2.2 adjust_numa_imbalance()函数

新增入参dst_weight,该修改目的是允许在node节点之间出现一点浮动的不均衡。

​ 当前,Linux系统中仅当目标节点完全空闲时才允许体现不平衡。 这能解决了一类基本问题,但有点过于谨慎。本次修改重新审视了 NUMA 节点可能不平衡直到 25% 的 CPU 被占用的可能性。 25% 是简要估算的(HT模式下,它是内核的50%)。 在较高的利用率下,平衡应继续正常进行,并保持平衡,直到调度程序域完全繁忙或过度使用。

​ 不过这也不是全场景绝对优化的,在某些测试场景下,该优化并不能体现出优势。需要具体情况具体分析。

请添加图片描述
请添加图片描述
(图左边是openEuler内核,右边是Linux5.10内核)

2.3 避免不必要的imbalance计算

该优化操作是在唤醒进程的慢速路径中。

在find_idlest_group()函数中,只有当group是overloaded或者fully busy状态下,才需要计算imbalance值。
请添加图片描述

2.4 find_idlest_group()函数

该操作是在唤醒进程的慢速路径中。

​ 原本是如果当前group有闲置算力,是在有idle的cpu情况下,才返回NULL,就是返回不必要查找idlest group。欧拉改为了只要当前group中25%以下占用,就认为还是idle的,不需要spill over任务到另一个node,也就是允许一定的不均衡存在(可能其他group有空闲cpu,当前group不是全idle的cpu,但任务占有率在25%以下)。我认为这样应该是减少了不必要的负载均衡迁移过程。

请添加图片描述

2.5 select_idle_core()函数

该操作是在唤醒进程的快速路径中。

​ 原本函数select_idle_sibling()中会调用select_idle_core()以及select_idle_cpu(),这两个函数会for循环,遍历同一个cpumask列表。这是一定的资源浪费。这两个函数是从上向下遍历不同层级调度域的,比如select_idle_core()遍历SMT层级,select_idle_cpu()遍历MC层级,但其实都是遍历的同一个cpumask列表。如何改进:将select_idle_core()放到select_idle_cpu()里面去做。

请添加图片描述

​ 当select_idle_cpu()在根据LLC域遍历查找空闲cpu时,也同时去执行select_idle_core()的遍历,这样要做的就是在遍历查找idle core的时候记住遇到的每个non-idle cpu(我的理解是只有非空闲的才需要下一层级也就是select_idle_core()再去遍历查找空闲cpu,否则就已经找到空闲的cpu了,所以这里是记住non-idle cpu),这样总共就只需要对整个cpumask列表遍历一次。

请添加图片描述
请添加图片描述
请添加图片描述

而在5.9.10的内核中,会执行更多的查找idle cpu操作,无疑这是低效率的:

请添加图片描述

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐