墙上时钟与 CPU 时间是两回事:纯计算 200 万次加法,两者几乎一样(0.13 秒 vs 0.12 秒);30 次 sleep 共 0.33 秒,占 CPU 是 0.000 秒。两者对不上,说明有别的东西在拖。
4.16 讲怎么算加速比,这一节把【时间】这个词拆开——你以后量任何东西,都得先问清【量的哪种时间】。
一、两种时间,两个意思
运行时间(墙上时钟/real):从开始到结束,你表上过去多久。这是用户感受到的那个时间。 执行时间(CPU 时间/user+sys):CPU 真正花在这个进程上的时间。它不包括等待。 两者的关系:real ≥ user + sys(单核时)。差值就是【等】的时间——等 IO、等锁、被别人挤。 多核时 real 可以小于 user+sys:多个核同时算,加起来超过墙上时间。
二、实测:两种活儿的两种时间
纯计算 200 万次加法:墙上 0.132 秒,占 CPU 0.125 秒。几乎没差。 30 次 sleep 各 10 毫秒:墙上 0.328 秒,占 CPU 0.000 秒。全在等。 同样是【跑了零点几秒】,一个是真干了活,一个是躺着等。 这个差别在排查问题时有决定性的作用:不知道是哪种,就会往错的方向优化。
三、三种组合与三种结论
real 大、user 小 → 在等 IO 或等锁 → 去查磁盘、网络、锁竞争。
real 大、user 也大 → 真在算 → 去查算法复杂度、向量化、缓存命中。
real 小、user 大 → 吃了多核 → 去确认是不是真并行、有没有超订。
这三条是性能排查的第一步,比任何 profiler 都快——time 就够了。
四、为什么 Linux 要分开记这两笔
因为调度器只认 CPU 时间:它按【谁占了多少 CPU】来分配。一个一直在等的进程,对调度器来说是【没占资源】的。 而用户只认墙上时间:他不管你在等还是在算,等了就是等了。 两套账各服务一个目的:内核用 CPU 时间做公平,用户用墙上时间评价体验。 所以【程序只用了 0.1 秒 CPU,但你等了三秒】这种情况完全可能——剩下 2.9 秒全在等。
五、动手 Demo:运行时间和执行时间——墙上时钟与 CPU 时间
两种活儿各跑一次,同时记墙上时钟与 CPU 时间:一段纯计算,一段全是 sleep。看两张表差在哪。
# ① 纯计算
t0, c0 = time.perf_counter(), time.process_time()
s = 0
for i in range(2000000):
s += i
t1, c1 = time.perf_counter(), time.process_time()
print("墙上", t1 - t0, "CPU", c1 - c0)
# ② 全在等
t2, c2 = time.perf_counter(), time.process_time()
for _ in range(30):
time.sleep(0.01)
t3, c3 = time.perf_counter(), time.process_time()
print("墙上", t3 - t2, "CPU", c3 - c2)
实跑输出:
--------------------------------------------------------------------
运行时间和执行时间——墙上时钟与 CPU 时间
--------------------------------------------------------------------
① 两种活儿的两种时间
干的活 墙上时钟 占 CPU 差值去哪了
---------------------------------------------------------------
纯计算 200 万次加法 0.125 秒 0.125 秒 几乎没差
sleep 30 次各 10 毫秒 0.329 秒 0.000 秒 全在等
**同样是在【跑】,一个是真干了活,一个是躺着等。**
**这就是 `time` 命令为什么要输出三行**:real 是墙上时钟,
user 与 sys 才是真花在 CPU 上的。**三者对不上,说明有别的东西在拖。**
② 这个区别在排查问题时最有用
现象 说明什么 接下来查什么
-------------------------------------------------------------
real 大、user 小 在等 IO 或等锁 磁盘、网络、锁竞争
real 大、user 也大 真在算 算法复杂度、向量化
real 小、user 大 多核并行 是不是真并行了
纯计算那组两个数几乎相等——0.13 秒与 0.12 秒,差的那点花在启动与收尾上。
sleep 那组差了两个数量级:墙上 0.328 秒,CPU 是 0.000 秒——因为睡着的时候一次也没占 CPU。
这就是 time 命令为什么要输出三行。real 是墙上,user 与 sys 才是真花在 CPU 上的。
排查时先看这一对:对不上就说明在等,顺着【在等什么】查下去,比盲猜快得多。
30 秒实验
time sleep 1——real 约 1 秒,user+sys 接近 0。这就是【纯等】的样子。time yes > /dev/null(按 Ctrl+C 停)——看 user 与 sys 各占多少。time dd if=/dev/zero of=/tmp/x bs=1M count=200——看 real 与 CPU 的差,那部分就是 IO 等待。
常见误区
- 【real 就是程序的执行时间】。real 含等待。程序本身的执行时间是 user+sys。
- 【CPU 时间短就说明程序高效】。它可能只是【大部分时间在等】。要看它等的是什么。
- 【多核下 real 一定比 user 小】。不一定。只有真并行且负载足够时才成立。
自测三问(点开对答案)
1. 运行时间与执行时间分别是什么?两者关系如何? —— 运行时间=墙上时钟;执行时间=CPU 时间(user+sys)。**单核时 real ≥ user+sys,差值就是等的时间**;多核时 real 可以小于它。 2. real 大而 user 小,说明什么?该往哪查? —— **在等** IO 或锁。**查磁盘、网络、锁竞争。** 3. 为什么内核和用户要记两套时间? —— 内核按 CPU 时间做公平分配;用户按墙上时间评价体验。**两套账服务两个目的。**- ☐ 4.18 进程睡眠
相关笔记
- 实验方法 — time 的三行
- 进程睡眠 — 等的时候在干嘛
- 进程的状态 — 睡眠就是 S 状态
- 🐧 Linux是怎样工作的 · 索引