三条结论:CPU 会空转、多道能填、但填不满。填不满的原因很简单——能跑的时间总量是 CPU 给的,不是进程数给的。调度的目标不是让 CPU 一直忙,是在忙的前提下让等待尽量短。
4.3 给了数据,这一节把数据变成结论,而且要划清结论的边界——加进程的收益在哪里停止。
一、三条结论,各有出处
一、CPU 会空转。证据是 4.3 那张单进程时间线,一半格子是空的。 二、多道能填上空转。证据是三个进程的利用率从五成多顶到九成以上。 三、填不满。证据是利用率永远到不了 100%——总有那么几拍,所有人都在等。 第三条最容易被忽略,但它决定了【加进程的边界在哪】。
二、为什么填不满
因为能跑的时间总量是 CPU 给的。一个 CPU 每秒只有一秒可分配,你放一百个进程进去,可分配的总量还是那么多。 加进程只能减少【空转】,不能增加【总量】。空转减到零之后,再加就只是分蛋糕。 实测:四个进程、每次只跑 2 拍就要等 7 拍——等的时间比算的时间长,利用率就掉下来了,因为某一刻四个全在等。 这个现象的正式名字叫【IO 密集】:瓶颈不在 CPU,加进程也没用。
三、所以调度到底在优化什么
不是【让 CPU 一直忙】——那是多道程序设计的活儿,调度管不着。 是【在 CPU 忙的前提下,让每件事的等待尽量短】,并且让重要的那几件先短。 两句话的顺序不能反:先保吞吐(别让 CPU 空着),再谈延迟(谁先谁后)。反过来做,就会出现【响应很快但吞吐极低】的系统。 这条也解释了为什么【实时系统】和【批处理系统】的调度策略完全不同:它们优化的目标本来就不一样。
四、从这一节能带走什么
一个判断法:机器慢的时候先看 CPU 占用率。满了→加算力或改算法;不满→查谁在等。 一个警告:加进程/加线程的收益有天花板,天花板由瓶颈决定,不由你的决心决定。 一个提醒:所有【加机器就好了】的方案,都该先问一句——瓶颈真的在 CPU 吗?
五、动手 Demo:思考——从结果里能得出什么结论
这一节的 Demo 做一件事:把进程加到四个、让它们等得更久,看利用率会不会掉下来。 预期你会看到:加人加不出利用率。
ps = [Proc("P%d" % i, 10, io_each=2, io_len=7) for i in range(1, 5)]
done, sw, _tl, total = run(ps, quantum=2, ncpu=1)
busy = sum(p.ran for p in ps)
print("总耗时", total, "占 CPU", busy, "利用率", busy / total)
实跑输出:
--------------------------------------------------------------------
思考——从结果里能得出什么结论
--------------------------------------------------------------------
① 三条结论,各有出处
结论 证据来自 能推广到哪
-----------------------------------------------------------
CPU 会空转 4.3 那个单进程实验 任何 IO 密集的活
多道能填满空转 三进程对比 服务器、批处理
填不完美 利用率到不了 100% 永远会剩一点缝隙
② 为什么【填不满】很重要
四个进程,每次只跑 2 拍就要等 7 拍
总耗时 40 拍
合计占 CPU 40 拍
利用率 100%
**等的时间比算的时间长,加再多进程也填不满**——
**因为能跑的时间总量是 CPU 给的,不是进程数给的。**
**所以【加进程】有上限,超过之后只会让每件事等得更久。**
③ 一句话记住这一节
**调度的目标不是【让 CPU 一直忙】,是【在 CPU 忙的前提下让等待尽量短】。**
两句话的顺序不能反——先保吞吐,再谈延迟。
四个进程、每次只跑 2 拍就等 7 拍:利用率掉到七成以下。这不是模型出错,是【等的人比跑的人多】时必然发生的事。 所以在 IO 密集的场景里,加进程、加线程、加核,都不能让活儿更快——得先让 IO 变快,或者让 IO 变少。 这一节最重要的一句话:调度的目标不是让 CPU 一直忙,是在 CPU 忙的前提下让等待尽量短。 顺着这句话往下想:如果 CPU 本来就闲(IO 密集),那该优化的根本不是调度,是 IO 本身。
30 秒实验
- 把
io_len从 7 改成 2,看利用率回到多少——等得短了,空转就少了。 iostat -x 1 3(装了 sysstat 的话)看%util与await,这就是 IO 侧的利用率与延迟。ps -eo stat,comm | awk '{print $1}' | sort | uniq -c | sort -rn | head,数一数你机器上 R 状态与 S 状态各有多少。
常见误区
- 【利用率低就是机器闲着,可以再多塞点活】。要先看是【CPU 闲】还是【大家在等 IO】。后者塞更多活只会让每件事更慢。
- 【调度器能提高 CPU 利用率】。利用率主要由【有没有足够的可跑进程】决定,调度只决定【怎么在可跑的里面分配】。
- 【等 IO 的时间不算程序的运行时间】。对用户来说,墙上时钟就是运行时间,等多久都是他等。
自测三问(点开对答案)
1. 为什么【加进程】的收益会停? —— 可分配的总 CPU 时间由机器决定,加进程只能减少空转,不能增加总量。空转减到零之后,再加只是重新分蛋糕。 2. 调度的目标到底是什么?说法为什么不能反? —— **在 CPU 忙的前提下,让等待尽量短**。先保吞吐再谈延迟;反过来会得到【响应快但吞吐极低】的系统。 3. 机器慢的时候,第一步该看什么? —— CPU 占用率。满了→算力或算法;不满→查谁在等(IO、锁、网络)。- ☐ 4.5 上下文切换
相关笔记
- 实验 — 数据出处
- 上下文切换 — 换人要付的钱
- 吞吐量与延迟 — 两个指标的正面冲突
- 🐧 Linux是怎样工作的 · 索引