COURSE SOURCES
仅作来源说明 · 不提供原始资料下载参考来源与版权说明
《性能之巅(第2版)》非官方个人学习笔记 · 内容为压缩转述 · 页码按 PDF 阅读器从 1 开始
01
START HERE
这章解决什么问题
应用发出一次读请求后,为什么有时消耗用户态 CPU,有时进入内核,有时睡眠,有时又在运行队列等待?本章提供解释这些现象的操作系统模型。内核负责调度、虚拟内存、文件系统、网络协议和设备驱动;应用通过库与系统调用请求特权服务。只有理解这条路径,才能把“进程没在跑”进一步解释成等待 CPU、I/O、锁、缺页或工作到来。
本章不要求记住所有内核实现,而是建立稳定概念,并提醒你:相同工具名在不同内核版本、配置、容器和虚拟机中可能看到不同范围的数据。
02
SECTION 02
五条核心结论
- 模式转换不等于上下文切换。 系统调用会从用户态进入内核态;只有线程阻塞、被抢占或调度给别的任务时,才发生任务上下文切换。
- 线程状态是性能导航图。 on-CPU、可运行等待、不可中断 I/O 等待和可中断睡眠,会把调查引向完全不同的资源。
- 内核通过抽象隐藏复杂性。 虚拟内存、VFS、套接字和设备驱动提供统一接口,也让一次请求跨越多层缓存和队列。
- 局部性影响调度质量。 CPU 亲和性、热缓存和 NUMA 内存位置会改变同一代码的执行成本。
- 版本与配置属于证据。 调度器、cgroup、PSI、eBPF、
io_uring等能力随内核演进;不能把另一台机器的行为直接套用。
03
SECTION 03
核心模型与关键指标
应用线程(用户态)
├─ 计算 ───────────────→ on-CPU 用户时间
└─ 系统调用 → 内核态 ──→ 内核时间 / 文件系统 / 网络 / 驱动
├─ 立即返回
└─ 阻塞 → 睡眠 → 中断/事件唤醒 → 可运行队列 → on-CPU- 用户时间与内核时间:分别表示执行应用代码和内核代码的 CPU 时间。高内核时间可由系统调用、中断或内核线程产生。
- 运行队列与调度延时:线程已具备运行条件,却在等 CPU;这是 CPU 饱和度的直接方向。
- 上下文切换:调度器保存一个任务并恢复另一个任务的执行上下文;频率高不自动等于有问题,要结合每次工作量与延时。
- 缺页故障:虚拟地址尚未具备所需映射。轻微缺页不访问磁盘,主要缺页可能等待存储,两者代价不同。
- 中断:设备完成 I/O 等异步事件可触发硬中断;软中断承担延后处理。中断工作消耗 CPU,却不一定记在目标进程名下。
- 缓存:从应用缓存、数据库缓存、页缓存到设备缓存,命中可避开慢层;缓存竞争也会把问题跨组件传播。
04
SECTION 04
诊断步骤
- 记录内核、发行版、架构、CPU 拓扑、容器/虚拟化边界与资源限制。
- 画出目标请求从应用函数到系统调用、VFS/网络栈和设备的路径,标明可能缓存与队列。
- 先按线程区分:正在用户态或内核态执行、可运行等待、
D状态等待、S状态睡眠,避免把所有 off-CPU 都叫作 I/O。 - 若用户时间高,剖析用户代码;若内核时间高,检查系统调用、中断和内核路径;若可运行等待高,检查 CPU 与配额。
- 若
D状态或主要缺页增加,沿文件系统、块 I/O 和内存压力继续;若大量S状态,区分等待工作、计时睡眠与锁等待。 - 检查是否只有单个 CPU、NUMA 节点或设备队列繁忙;整体均值可能掩盖局部热点。
- 用版本文档核实指标来源和功能开关,再选择更深的 tracepoint、kprobe 或 BPF 工具。
05
SECTION 05
常用工具与命令
uname -a
cat /proc/version
lscpu
cat /proc/loadavg
ps -eLo pid,tid,psr,stat,pcpu,comm
cat /proc/interrupts
cat /proc/softirqs
cat /proc/self/status
systemd-analyze
systemd-analyze critical-chain这些命令只读取状态。ps 的字段和格式在不同实现中可能略有差异;systemd-analyze 仅适用于使用 systemd 的系统。/proc/interrupts 在容器内可能不可见或只反映命名空间允许的范围。若要用 strace、调试器或逐事件跟踪附加生产进程,应先在测试环境评估开销,因为它们可能改变目标时序。
06
SECTION 06
如何解读结果
STAT=R表示正在运行或可运行,不代表此刻一定占有 CPU;D通常表示不可中断睡眠,常见于 I/O,但还需栈或事件证据;S可能只是正常等待工作。- 一个系统调用若立即完成,可能只有用户态/内核态模式转换;阻塞调用才可能让调度器切换到其他线程。
psr显示线程最近所在 CPU。大量工作集中在一个逻辑 CPU,可能是单线程、亲和性、锁或中断映射问题。/proc/interrupts与/proc/softirqs是累计计数;应按时间取差值,并查看是否集中在特定 CPU,不能直接比较不同运行时长的主机。- 启动慢时,
systemd-analyze critical-chain显示关键依赖路径;blame的单项耗时不一定处于真正阻塞启动完成的路径上。 - 虚拟机或容器内看到的是被虚拟化和限制后的系统。主机空闲不代表租户未被 CPU 配额、内存上限或 I/O 控制节流。
07
SECTION 07
常见误判
- 把每次系统调用都叫上下文切换。 两者开销、原因和优化方向不同。
- 把 Linux 平均负载等同 CPU 队列。 它还可包含不可中断睡眠任务。
- 看到 `D` 就断言磁盘坏。 文件系统、网络文件系统、设备驱动或其他内核等待都可能出现类似状态。
- 只看进程不看线程。 单个热点线程会被进程平均值掩盖,多线程也可能受同一把锁限制。
- 把空闲内存少当作内存泄漏。 内核会利用内存做缓存,应结合可用内存、回收、换页与压力判断。
- 照搬旧内核经验。 cgroup 版本、I/O 调度器、PSI 和跟踪接口的可用性会改变指标含义与工具行为。
08
SECTION 08
五分钟自测
- 用一句话区分模式转换和上下文切换。
- 一个线程的
STAT为R、D、S时,各自下一步最值得查什么? - 为什么进程用户时间低,系统仍可能有很高的 CPU 消耗?
- 写出一次缓存未命中的文件读取可能经过的三层内核路径。
- 在容器内看到 CPU 空闲时,为什么仍要检查 cgroup 限制?
09
SECTION 09
本章小结
操作系统把应用与硬件连接起来:系统调用进入内核,调度器决定线程何时在哪颗 CPU 运行,虚拟内存和文件系统管理地址与数据,驱动及中断连接设备。诊断时先认清线程状态和执行模式,再沿实际数据路径深入;同时把内核版本、配置与资源边界纳入证据,避免把抽象接口误当成完整真相。
10
SECTION 10
来源定位
| 主题 | PDF 页码 |
|---|---|
| 操作系统术语与内核模型 | 142-146 |
| 用户态/内核态、系统调用与中断 | 146-151 |
| 时钟、进程生命周期与栈 | 152-157 |
| 虚拟内存、调度器与文件系统 | 157-161 |
| 缓存、网络、驱动、多处理器和资源管理 | 161-164 |
| UNIX、BSD、Solaris 与 Linux 背景 | 165-168 |
| Linux 性能能力、systemd 与 eBPF | 168-175 |
| 其他内核主题、比较与参考资料 | 175-181 |
📝
QUICK CHECK
章节测验
共 5 道单选题。答错有解析,答对看来源页码。
单选题 · 第 1/5 题
已答 0/5