fork之后是子历程先实行照旧父历程先实行
CFS(完全公平调理器)是Linux内核2.6.23版本开始采用的历程调理器,它的基本原理是如许的:设定一个调理周期(sched_latency_ns),目的是让每个历程在这个周期内至少有机会运行一次,换一种说法就是每个历程等待CPU的时间最长不超过这个调理周期。然后根据历程的数量,大家平分调理周期内的CPU利用权。由于历程的优先级,即nice值差别,分割调理周期的时间要加权。每个历程的累计运行时间生存在自己的vruntime字段里,哪个历程的vruntime最小就获得本轮运行的权利。那么问题就来了:新历程的vruntime的初值是不是0?
假如新历程的vruntime初值为0的话,比老历程的值小很多,那么它在相称长的时间内都会保持抢占CPU的上风,老历程就要饿死了,这显然是不公平的。以是CFS是如许做的:每个CPU的运行队列cfs_rq都维护一个min_vruntime字段,记录该运行队列中所有历程的vruntime最小值,新历程的初始vruntime值就以它所在运行队列的min_vruntime为基础来设置,与老历程保持在合理的差距范围内。
fork出来的新历程的vruntime初值的设置与两个参数有关:
sched_child_runs_first:规定fork之后让子历程先于父历程运行;
sched_features的START_DEBIT位:规定新历程的第一次运行要有耽误。
sched_features是控制调理器特性的开关,每个bit表现调理器的一个特性。在sched_features.h文件中记录了全部的特性。START_DEBIT是其中之一,如果打开这个特性,表现给新历程的vruntime初始值要设置得比默认值更大一些,如许会推迟它的运行时间,以防历程通过不停的fork来获得cpu时间片。
如果参数 sched_child_runs_first打开,意味着创建子历程后,保证子历程会在父历程之前运行。子历程在创建时,vruntime初值首先被设置为min_vruntime;然后,如果sched_features中设置了START_DEBIT位,vruntime会在min_vruntime的基础上再增大一些。设置完子历程的vruntime之后,查抄sched_child_runs_first参数,如果为1的话,就比较父历程和子历程的vruntime,若是父历程的vruntime更小,就对换父、子历程的vruntime,如许就保证了子历程会在父历程之前运行。
休眠历程的vruntime不停保持不变吗?
如果休眠历程的 vruntime 保持不变,而其他运行历程的 vruntime 不停在推进,那么等到休眠历程终于唤醒的时间,它的vruntime比别人小很多,会使它获得长时间抢占CPU的上风,其他历程就要饿死了。这显然是另一种形式的不公平。CFS是如许做的:在休眠历程被唤醒时重新设置vruntime值,以min_vruntime值为基础,给予一定的补偿,但不能补偿太多。
休眠历程在唤醒时会立刻抢占CPU吗?
这是由CFS的唤醒抢占特性决定的,即sched_features的WAKEUP_PREEMPT位。
由于休眠历程在唤醒时会获得vruntime的补偿,以是它在醒来的时间有本领抢占CPU是大概率事件,这也是CFS调理算法的本意,即保证交互式历程的相应速度,因为交互式历程等待用户输入会频繁休眠。除了交互式历程以外,主动休眠的历程同样也会在唤醒时获得补偿,例如通过调用sleep()、nanosleep()的方式,定时醒来完成特定任务,这类历程往往并不要求快速相应,但是CFS不会把它们与交互式历程区分开来,它们同样也会在每次唤醒时获得vruntime补偿,这有可能会导致其它更告急的应用历程被抢占,有损整体性能。
案例说明
我曾经处理过一个案例,服务器上有两类应用历程:
A历程定时循环查抄有没有新任务,如果有的话就简单预处理后关照B历程,然后调用nanosleep()主动休眠,醒来后再重复下一个循环;
B历程负责数据运算,是CPU斲丧型的;
B历程的运行时间很长,而A历程每次运行时间都很短,但睡眠/唤醒却非常频繁,每次唤醒就会抢占B,导致B的运行频繁被打断,大量的历程切换带来很大的开销,整体性能降落很厉害。
那有什么办法吗?有,末了我们通过克制CFS唤醒抢占 特性办理了问题:
# echo NO_WAKEUP_PREEMPT > /sys/kernel/debug/sched_features
禁用唤醒抢占特性之后,刚唤醒的历程不会立即抢占运行中的历程,而是要等到运行历程用完时间片之后。在以上案例中,颠末如许的调整之后B历程被抢占的频率大大降低了,整体性能得到了改善。
历程从一个CPU迁移到另一个CPU上的时间vruntime会不会变?
# grep min_vruntime /proc/sched_debug
.min_vruntime : 12403175.972743
.min_vruntime : 14422108.528121
如果一个历程从min_vruntime更小的CPU (A) 上迁移到min_vruntime更大的CPU (B) 上,可能就会占便宜了,因为CPU (B) 的运行队列中历程的vruntime普遍比较大,迁移过来的历程就会获得更多的CPU时间片。这显然不太公平。
CFS是如许做的:
当历程从一个CPU的运行队列中出来 (dequeue_entity) 的时间,它的vruntime要减去队列的min_vruntime值;
而当历程参加另一个CPU的运行队列 ( enqueue_entiry) 时,它的vruntime要加上该队列的min_vruntime值。
如许,历程从一个CPU迁移到另一个CPU之后,vruntime保持相对公平。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]