10 行代码玩转弹性调度的小把戏(弹性调班什么意思)
作者 | dog250
责编 | 唐小引
头图 | CSDN 下载自东方 IC
出品 | CSDN
Linux 的进程调度器是通用的调度器,无论是 O(n)O(n),O(1)O(1),还是 CFS,均是基于统一的指标来对待所有进程的。也就是说,进程甚至无法自主退让。
只要确定了一个进程的优先级,无论是是什么调度算法,该进程的地位总是不会变化,如果能做到下面的策略就好了:
-
系统中进程多了,就加速退让。
系统中进程少了,就加速抢占。
工人来了,就退让。
经理来了,就抢占。
……
考虑一个进程 A 在一个特定的系统中运行,它最多只能用 40%的 CPU,此时,如果有另外的待运行进程,那么这些进程自然分摊另外 60%的 CPU,如果再来一个进程 A 呢?显然,两个进程 A 的 CPU 时间均会减少。
能不能保证两个进程 A 仍然分别使用 40%的 CPU,然后其它进程分摊剩余 20%的 CPU 呢?很难!
你可能说可以配 group 啊,但是这必须有一个静态的配置过程,很难动态自适应。
换句话说,Linux 的调度器是非弹性的!
下面的代码展示了一个简单的弹性调度:
#!/usr/local/bin/stap -g
probe kernel.function("__enqueue_entity")
{
task = _task_of($se)
pid = @cast(task, "struct task_struct")->pid
if ($1 == pid) {
_nr = $cfs_rq->nr_running
t = $se->vruntime;
$se->vruntime = t 3000000*(_nr - 1)
}
}
意思是指定进程根据系统中负载的数量来退让:
-
系统负载越高,指定进程占有 CPU 时间比例越低。
系统负载越低,指定进程占有 CPU 时间比例越高。
来来来,看效果:
可以看到:
-
当只有一个 loop 的时候,它占用 100%的 CPU。
当再生一个 loop 的时候,它几乎和第一个 loop 平分 CPU。
当越来越多的 loop 运行的时候,第一个 loop 的 CPU 份额逐渐降低。
本是同根生,只有第一个 loop 被弹性了。
嗯,效果还行,但不够平滑。试试二次曲线, or 三次曲线?
$se->vruntime = t 200*(_nr - 1)*_nr*_nr
// or
// $se->vruntime = t 20000*(_nr - 1)*_nr
200 何来?调一手好参数是必要的。
此外,我这里弹性策略过于单一,其实是可以设计的足够复杂的,比如针对特定进程的特定策略,即便是简单的双斜率直线段,也比我这个 OK,是吧,不多说。
有人问,如何找到要修改的代码在哪里,只要对 Linux 内核的执行原理足够熟悉,这并不难,对于手艺人而言,阿基米德,鲁班,庖丁,黄道婆这些人的地位是堪比欧几里得,笛卡尔的。
原文链接:https://blog.csdn.net/dog250/article/details/108281228
点分享