Open arthur-zhang opened 3 years ago
[TOC]
如果系统中有一个实时进程且可运行,那么调度器总是会选择它,除非另有一个优先级更高的实时进程
吞吐 vs 响应:
响应:最小化某个任务的响应时间,哪怕牺牲其他的任务为代价。
吞吐:全局视野,整个系统的workload被最大化处理。
任何操作系统的调度设计都需要最大化的追求2个目标:吞吐率大和延迟低。但是这两个目标却是有些冲突,是相对的,整个系统的吞吐率大,意味着CPU必须尽量的最大限度的工作,不要让cpu空闲下来,但是要求响应低,则必须在优先级高的进程在需要的情况下随时可以抢占进来,打断别人,强行插队,但是,抢占会引起上下文切换,上下文切换的时间本身对吞吐率来讲,是一个消耗(上下文切换更大的消耗不是切换本身,而是切换会引起大量的cache miss。你明明微博跑的很爽,现在切过去微信,那么CPU的cache是不太容易命中微信的)
操作系统中估算"上下文切换"对吞吐能力影响时,不是计算上下文切换本身,而是在CPU 高速cache中的miss。一旦从一个进程切到另一个进程,会造成比较多的cache miss,从而影响吞吐能力。
CPU密集型:对CPU的的性能要求比较高,要求多数时间花在CPU上面(做运算)
IO密集型:对CPU的性能要求不高,进程的运行效率主要受限于I/O速度,但是对于进程的响应非常敏感(CFS)
IO 消耗型对拿到CPU(延迟)比较敏感,应该被优先调度。一般需要CPU的响应速度快,即优先级要求比较高
实时调度
可以看到 SCHED_FIFO 和 SCHED_RR 的区别只是体现在同等级优先级的处理上,SCHED_FIFO 在同等级优先级按照先进先出的处理,但是 SCHED_RR 在同等级下的处理是轮转调度
普通调度
./fake_make -j2
, 查看cpu占用率和进程调度策略新创建的线程,如果不知道调度策略,则默认都是SCHED_OTHER(SCHED_NORMAL),基于CFS的完全公平调度策略,可以跑满整个CPU
sudo chrt -f -a -p 30266
可以看到被修改成FIFO的进程的CPU占用率, 达到接近 190%
另一个处于NORMAL的进程的CPU占用率,接近10%
sudo chrt -f -a -p 30 6525
sudo chrt -f -a -p 20 6548
可以看到只有一个 6525 的进程执行,CPU的使用率接近190%,符合优先级越高,优先执行的情况,并且因为进程是死循环,先执行的永远不会结束,优先级低的永远不会执行
sudo chrt -f -a -p 30 6525
sudo chrt -f -a -p 30 6548
可以看到只有一个 6525 的进程执行,CPU的使用率接近190%,符合优先级相同,先进先出的策略
这是因为操作系统设置实时进程在一个运行周期(sched_rt_period_us)内,最多占用CPU运行时间为 sched_rt_runtime_us
在linux中,这两个参数默认为
sched_rt_period_us = 1s
sched_rt_runtime_us = 0.95s
所以对于单核的机器,设置了实时调度策略后,最多可以占用到95%的CPU,双核的机器最多占用190%的CPU
./fake_make -j2
sudo chrt -r -a -p 30 13225
现象和上面的FIFO的同样的操作一样
可以看到被修改成RR的进程的CPU占用率, 达到接近 190%
另一个处于NORMAL的进程的CPU占用率,接近10%
sudo chrt -r -a -p 30 13225
sudo chrt -r -a -p 40 13211
和FIFO的相同步骤一样,符合不同优先级,高优先级的先执行
sudo chrt -r -a -p 30 13225
sudo chrt -r -a -p 30 13211
和FIFO的相同步骤不一样,符合对于RR策略,相同优先级的轮训执行
./fake_make -j2
sudo renice -n -5 -g 29962
查看CPU使用率变化情况修改为-5 的renice值的进程的CPU使用率变为 150%,没有修改的进程的CPU使用率为50%
CFS的调度原理是根据vruntime 构建一个红黑树,通过这个红黑树每次都会调度vruntime最小的进程,同时vruntime又是不断变化的,所以也会不停的调整红黑树,保证每次获取到的都是vruntime最小的进程
vruntime的计算规则
虚拟运行时间 vruntime += 实际运行时间 delta_exec * NICE_0_LOAD / 权重
根据vruntime的计算规则,我们可以知道,vruntime的变化是基于实际运行的时间* NICE_0_LOAD(1024) /prio_to_weight[NICE] 值
比如在上面CFS的实操中:
1. 对于上面设置的NICE值为 -5 的进程:29926
vruntime(NICE:-5) += delta_exec * 1024 / 3121
2. 对于普通线程来说(NICE值为0):29992
vruntime(NICE:0) += delta_exec * 1024 / 1024
可见在相同的 delta_exec 情况下,(NICE:-5) 的进程执行三次的vruntime 才会和(NICE:0)的进程一样,所以 29926 的CPU占用率和 29992 的CPU占用率呈现3:1的比例也就可以理解了
CFS的思想就是让每个调度实体(没有组调度的情形下就是进程,以后就说进程了)的vruntime互相追赶,而每个调度实体的vruntime增加速度不同,权重越大的增加的越慢,这样就能获得更多的cpu执行时间。
需要注意点的这个里面设置的进程优先级的值是值越大,进程优先级越高
比如:
sudo chrt -r -a -p 40 13211
的优先级大于sudo chrt -r -a -p 30 13225
需要注意 renice的设置需要在
sudo sysctl -w kernel.sched_autogroup_enabled=0
(修改完需要重新登录)的情况下设置eg.
sudo renice -n -5 -g 29962
### (1)实时进程调度 linux下进程是分优先级的,0级到99级是分给实时进程的,100级到139级是分给非实时进程的
在实时进行调度下,有两个参数特别重要啊:
sysctl -n kernel.sched_rt_period_us # 实时进程调度的单位CPU时间 1 秒
1000000
sysctl -n kernel.sched_rt_runtime_us # 实时进程在 1 秒中实际占用的CPU时间, 0.95秒
950000
我们可以使用命令来修改进程的调度策略和优先级
sudo chrt -r -a -p 20 13421 # 使用rr调度策略,并调整13421的优先级为20
当我们启动两个实时进程时
我们可以看到其中一个实时进程占用了95%的CPU,这里的计算就是根据上面参数的,另外一个实时进程需要等前面的执行完才会执行。
### (2)nice值对进程调度的影响 对于非实时进程的调度,是通过CFS调度器来实现的,CFS调度器的核心是虚拟运行时间vruntime。虚拟运行时间跟进程运行时间和优先级有关,进程占用CPU时间越长,进程优先级越低,其vruntime就越大
vruntime=delta *(NICE_0_LOAD/ weight)
我们可以通过renice设置进程的 NICE值
sudo renice -n -5 -p 14797
我们启动两个非实时进程,两个进程的CPU占用比较均衡
接下来我们修改 14798进程的nice值 sudo renice -n -5 -p 14797
修改完后,14798进程的 weight 会变大,相关的vruntime就变小,线程优先级就越大
通过上表,可以看到nice=0和nice=-5的权重基本就是1 :3,下图展示了修改后的情况,相应的CPU占用也是 3:1
1、实时进程调度算法的一些问题探究 sched_rt_period_us sched_rt_runtime_us 参数的理解 2、nice 值对 CFS 调度算法的影响实例演示 3、chrt 和 renice 命令的使用
sudo renice -n -5 -g 14822 sudo chrt -f -a -p 60 12615
作业: 1、通过 chrt 验证 RR 调度算法 CPU 占用的变化 2、通过 renice 验证不同 nice 值对 CPU 占用的影响