1. 吞吐率和响应
吞吐:单位时间内做的有用功;
响应:低延迟。
吞吐追求的整个系统CPU做有用功,响应追求的是某个特定任务的延迟低;
1GHZ的CPU切换线程保存恢复现场约几个微妙级别,看似消耗不了太多时间,但是由于系统的局部性原理,会保存当前线程数据的缓存,切换线程会打乱局部性引起cache miss,而CPU访问cache速度远大于内存访问,这样综合看来上下文切换花销还是很大的。无用功占用较多CPU;
追求吞吐量和低延迟,这两个目标是矛盾的
编译内核选项有如下
服务器版追求吞吐量,配置为不抢占;桌面版或手机更追求响应,配置为低延迟;
调度器一般讲的是最后一种,低延迟抢占;
2. Linux任务类型
问题2: 一个典型的系统内任务分两种:CPU消耗型和IO消耗型
CPU型的任务,通常要求高性能,但是不追求低延迟,优先级较低;
IO型的任务,通常优先级更高,追求低延迟,对CPU性能不敏感;
如下图,一个读IO循环过程,占用CPU时间极短(1ms),IO占用100ms
,若CPU性能降一倍,执行CPU占用2ms对整体时间影响不大(总时间102ms);但是如果CPU不能及时响应,一个读写周期响应延迟100ms,那整体时间变为约200ms,整体性能降低一半;
所以,IO型任务只关注响应速度,对CPU性能不敏感;
基于此原理ARM公司设计了big.LITTLE架构,比如在手机上有8个核,设计为四大核,四小核;大小核指令集完全兼容,调度器调配IO型的任务跑在小核上(对CPU弱不敏感),CPU型任务放在大核上跑。这样用4+1(四小核等效)核的功耗实现了8核的性能;
调度器要在吞吐和延迟之间找到某个均衡;
3 任务调度
1调度原理:
涉及两个概念,策略和优先级;
内核所有进程优先级为0~139之间;
0~99:采用RT策略,常用的有SCHED_FIFO, SCHED_RR;
SCHED_RR, 不同优先级与CHED_FIFO相同,属于霸占型,同等优先级轮转;
比如有4个进程:P1_FIFO_3, P2_CHED_RR_2, P3_CHED_RR_2, P4_FIFO_4
执行过程,P2/P3轮转执行完之后,执行P1, 最后执行P4。
100~139:普通线程,采用非RT策略,对应nice(-20, 19).
这里所有优先级都是可以抢占的,但nice 值越低,分配CPU资源越多。
2.所有调度,SCHER_FIFO/SCHER_RR或设置nice都是针对task_struct;
3.将进程设置为FIFO策略:
修改进程25020的策略为FIFO, 优先级50
sudo chrt –f –a –p 50 25020
这样进程是按FIFO策略调度,占有CPU最高为80%(普通进程可以接近100%),CPU占有率降低(但不可抢占),此时IO延迟反而变大,鼠标操作变慢;
设置FIFO线程api
内核里优先级=99-50=49
内核态数字越低,优先级越高;用户态相反;
4.每个task_struct的nice都可以单独设置(所有普通线程);
Nice值设置都是指普通线程,RT策略不支持nice;
nice()默认是0
调度,在不同nice值进程间轮转,
2.6早期内核对进程采取奖励和惩罚算法,越睡眠越奖励,越消耗CPU,越惩罚,动态调整nice值,实现极其复杂,后来升级两个补丁;
补丁1:RT熔断机制,设置rt门限值
默认runtime 0.95s,period 1s,1s内RT最多跑了0.95s自动熔断;
$cd /proc/sys/kernel
sudo sh -c ‘echo 800000 > sched_rt_runtime_us’
设置RR/FIFO策略熔断最高位800ms,RR/FIFO策略进程最多占用CPU 80%。(默认是95%)
补丁2:普通进程调度算法CFS(complete fare schedule)
虚拟运行时间,vtime = ptime * 1024/weight
ptime:物理时间
weight:权重参数
nice=0,虚拟时间等于物理时间;
nice值越小,对应weight分母越大,vtime增长越慢,实际对应ptime占用越多;
vtime机制很好的平衡了I/O型,CPU型任务;
I/O型喜欢睡眠,ptime比较小,所以vtime自然较小,会偏向于挂在树左边;
同理,优先级越高的CPU型,其weight值越大,vtime也会越小,亦偏向挂载树左边;
即CFS用很简单的方式实现了历史上复杂的睡眠补偿,消耗惩罚,动态调整等功能;
修改进程的nice值:
sudo renice -n -5 -g 24856 //24856进程的所有线程nice都设置为-5
综上,linux调度算法过程:
1.首先执行SCHECH_RR/SCHECH_FIFO进程,待他们执行到睡眠或者熔断,CPU切换到普通线程;
2.普通线程按CFS算法调度,在普通线程间轮转;
线程调度优先与线程是否在内核态无关,只由优先级和策略决定。用户态内核态只涉及权限问题;
关于CFS实现细节,参考多年前的一篇文章
http://blog.chinaunix.net/uid-24708340-id-3787960.html