这个场景解决什么
top 或 mpstat 里 us(用户态)不高,sy(系统态)却长期偏高,意思是 CPU 的时间被内核代劳占走了:处理系统调用、应付中断、回收内存、维护锁与调度。它和「业务代码算得慢」是完全不同的两类问题,处置手段也不一样。排查思路是先看分布(是某一核还是普遍高),再按网络中断、系统调用、资源竞争三个方向收敛。
基本信息
| 适用场景 | 系统态 CPU 占比高,但找不到用户态的热点进程 |
|---|---|
| 目标 | 把 sy 的来源归类到网络、系统调用或资源竞争 |
| 工具链 | mpstat、/proc/softirqs、/proc/interrupts、pidstat -w、perf top |
| 判断要点 | 先看是否集中在个别核,再区分中断驱动与调用驱动 |
典型使用场景
- 网络压力:小包洪峰或收包集中在一个核,软中断吃掉大量 CPU
- 系统调用风暴:程序频繁 open/close、读写小文件、fsync,内核开销远超业务计算
- 内存回收:内存吃紧触发 kswapd 与直接回收,表现为 sy 高且伴随明显 IO
- 锁与调度:上下文切换异常多,线程在等锁与抢 CPU 之间空转
- 容器与虚拟化环境:宿主的开销计入容器视角的 sy,跨层对比时要留出解释空间
第 1 步:确认分布在哪些核
第 1 步:确认分布在哪些核
mpstat -P ALL 1 3 # 逐核看 us/sy/soft/steal
vmstat 1 5 | tail -n +3 # r 队列、cs 上下文切换、si 中断
cat /proc/loadavg # 负载里能看到运行与阻塞任务比例第 2 步:中断与调用
第 2 步:中断与调用
cat /proc/softirqs | head -n 12 # NET_RX、TIMER、RCU 各核计数差异
cat /proc/interrupts | head -n 20 # 硬中断分布,看是否挤在一个核
pidstat -w 1 3 | tail -n +4 | sort -k5 -rn | head # 谁在疯狂切换上下文
pidstat -u 1 3 | sort -k8 -rn | head # 内核态占比高的进程第 3 步:进一步定位
第 3 步:进一步定位
perf top --no-children 2>/dev/null | head -n 20 # 看内核态热点函数
strace -f -c -p <PID> 2>/dev/null # 短暂统计系统调用分布,慎用
cat /proc/pressure/cpu # PSI:看 CPU 压力与等待时间常见 sy 高来源与特征
| 来源 | 典型特征 | 下一步 |
|---|---|---|
| 网络软中断 | NET_RX 计数集中在一两个核,soft 占比高 | 看队列与网卡多队列、RPS,检查是否有小包洪峰 |
| 系统调用密集 | 某进程 %system 高,cswch 同步升高 | strace 统计调用分布,考虑批量与缓冲优化 |
| 内存回收 | kswapd 活跃,si/so 出现换页,IO 上升 | 查内存水位与 cgroup 限制,避免持续贴着上限 |
| 锁与调度 | nvcswch 高,负载高但吞吐不涨 | 看线程数与锁竞争,评估并发模型 |
| 文件系统同步写 | fsync 相关调用频繁,磁盘延迟升高 | 检查写入策略,合并小写 |
容器里读到的 sy 包含宿主代容器执行系统调用的成本,也可能包含 steal(被其他虚拟机抢走的时间)。跨宿主机与容器两侧对比时要先说明口径,否则会把宿主的开销算到应用头上。
受限环境(无 CAP_PERFMON、容器未放开权限、隐藏的 perf_event_paranoid 限制)里 perf 不可用,此时回退到 mpstat、pidstat 与 /proc 计数这套组合,不要因为一个工具报错就停下排查。