Linux CPU调度、负载与性能分析实战

CPU问题不只表现为使用率100%。系统可能CPU使用率不高却延迟很大,也可能Load Average很高但CPU仍空闲。排障必须区分运行队列、不可中断I/O、软中断、锁竞争、上下文切换、虚拟化Steal、频率降级和NUMA远端访问。

一、先理解Load Average

Linux Load Average统计可运行任务以及不可中断睡眠任务的平均数量,不等于CPU利用率。

uptime
cat /proc/loadavg

判断Load需结合CPU数量、运行队列和D状态任务。8核主机Load 8可能刚好满载,也可能由I/O等待造成;Load 2也可能让单线程关键服务达到瓶颈。

二、CPU时间分类

mpstat -P ALL 1
top

常见字段:

  • user:用户态;
  • system:内核态;
  • iowait:CPU空闲且有任务等待I/O;
  • irq/soft:硬中断和软中断;
  • steal:虚拟机等待宿主机CPU;
  • guest:运行虚拟CPU;
  • idle:空闲。

总CPU平均值会掩盖单核热点,应始终查看每个CPU。

三、快速基线

mpstat -P ALL 1
pidstat -u -w -t 1
vmstat 1
ps -eo pid,ppid,psr,stat,comm,%cpu --sort=-%cpu | head -30

同时记录业务QPS、P95/P99、错误率、线程池、GC和下游延迟。CPU指标离开业务吞吐没有意义。

四、运行队列与调度等待

vmstat 的 r 表示可运行任务数。长期明显高于可用CPU说明竞争,但短时突发可能正常。

cat /proc/schedstat
cat /proc/<pid>/sched

关注:

  • 运行等待时间;
  • 上下文切换;
  • 进程迁移;
  • 单线程热点;
  • Cgroup CPU限额;
  • CPU亲和性。

五、上下文切换

pidstat -w 1
vmstat 1

自愿切换通常是等待锁、I/O或条件变量;非自愿切换通常是时间片耗尽或被更高优先级任务抢占。

上下文切换高可能来自线程过多、锁竞争、短任务、频繁系统调用或超细粒度并发。不要简单把线程数调得更大。

六、找热点线程

top -H -p <pid>
pidstat -t -p <pid> 1
ps -L -p <pid> -o pid,tid,psr,stat,pcpu,comm

Java线程ID常以十进制显示,线程Dump中可能是十六进制,需要转换关联。高CPU线程可能是业务计算、GC、JIT、加密、压缩或死循环。

七、perf方法

perf stat -p <pid> sleep 10
perf top -p <pid>
perf record -F 99 -g -p <pid> -- sleep 30
perf report

perf stat可观察cycles、instructions、cache miss、branch miss和上下文切换。IPC低可能来自内存等待、分支预测失败或锁竞争。

采样会带来开销,生产应短时、限制频率,并确认安全策略允许获取符号。

八、火焰图

火焰图宽度代表采样占比,不代表时间顺序。需要:

  • 正确符号和调试信息;
  • 合适采样窗口;
  • 覆盖异常时段;
  • 区分CPU火焰图、Off-CPU和内存火焰图;
  • 与业务请求关联。

CPU火焰图看不到等待锁和I/O的时间,需配合Off-CPU分析。

九、软中断与网络热点

cat /proc/softirqs
cat /proc/interrupts
mpstat -P ALL 1
ethtool -l <interface>

单核softirq高会限制网络吞吐。检查IRQ亲和性、RSS/RPS/XPS、多队列、网卡驱动和包大小。不要在不了解NUMA和队列映射时随意手工绑中断。

十、D状态与高Load

ps -eo state,pid,ppid,wchan:32,comm | awk '$1 ~ /D/'
cat /proc/<pid>/stack

D状态常表示不可中断等待,可能来自磁盘、NFS、块设备、驱动或内核锁。杀进程通常不能立即结束,需处理底层等待原因。

十一、虚拟化Steal

虚拟机的steal升高表示宿主机没有及时分配物理CPU,常见于超分或邻居噪声。

排查:

  • 云监控或虚拟化平台CPU争用;
  • vCPU数量与NUMA;
  • 宿主机CPU Ready;
  • Burst积分;
  • 迁移到其他宿主机;
  • 实例规格。

虚拟机内部调优无法解决宿主机争用。

十二、CPU频率与温度

lscpu
cpupower frequency-info
grep -E 'cpu MHz' /proc/cpuinfo
sensors

高温、功耗限制、BIOS电源策略和虚拟化配置可能让频率下降。CPU利用率相同但频率不同,业务吞吐会明显变化。

生产服务器要结合性能、功耗和延迟目标选择Governor,不盲目锁定最高频率。

十三、NUMA与CPU亲和性

numactl --hardware
numastat
taskset -pc <pid>

绑核可以减少迁移,但也可能把任务限制在少数CPU或造成中断和应用争抢。CPU亲和性要与内存、网卡、NVMe和GPU所在NUMA节点共同设计。

十四、Cgroup CPU限制

Cgroup v2:

cat /sys/fs/cgroup/<group>/cpu.max
cat /sys/fs/cgroup/<group>/cpu.stat
cat /sys/fs/cgroup/<group>/cpu.pressure

nr_throttled和throttled_usec持续增加说明受到CPU quota限制。容器看似CPU没有打满,也可能每个调度周期都被节流。

Kubernetes中请求影响调度和权重,限制触发节流。对延迟敏感服务要通过压测决定是否设置过紧limit。

十五、PSI CPU

cat /proc/pressure/cpu

CPU PSI表示任务因等待CPU而停顿的时间。它比单纯CPU利用率更接近资源压力,可用于弹性伸缩和过载保护,但仍需结合吞吐和延迟。

十六、锁竞争

高CPU不一定都是有效计算。自旋锁、互斥锁和原子竞争会消耗CPU。

工具:

  • perf lock;
  • perf c2c;
  • eBPF lock工具;
  • 语言运行时Profile;
  • Java Flight Recorder;
  • Go mutex/block profile。

治理可能是缩小共享状态、分片锁、批处理、减少线程或改变算法。

十七、调度策略与优先级

普通任务通常使用CFS。nice影响权重,不保证固定CPU比例。实时调度 SCHED_FIFO/RR 可饿死普通任务,必须限制权限、CPU和运行时间。

chrt -p <pid>
renice -n 5 -p <pid>

不要用实时优先级解决普通业务延迟。

十八、语言运行时

Java

区分业务线程、GC、JIT和VM线程。结合GC日志、JFR、线程Dump和async-profiler。

Go

结合CPU pprof、Goroutine、Block和Mutex Profile。高Goroutine不一定高并发能力。

Node.js

单事件循环可能单核打满,检查同步CPU任务、JSON、正则和Native扩展。Worker Thread不是默认万能解法。

Python

CPU密集线程受GIL影响,考虑多进程、Native库或任务队列,同时注意进程复制内存。

十九、常见场景

CPU 100%

定位到进程和线程,区分user/system/softirq,采样热点;确认业务吞吐是否同步上升。若吞吐不升,重点看锁、GC、重试和死循环。

CPU不高但延迟高

检查单核、quota节流、Steal、D状态、锁等待、下游和队列。总CPU平均值最容易误导。

Load高但CPU空闲

检查D状态、I/O、NFS、块设备和内核栈。

扩容CPU后无改善

检查单线程瓶颈、锁、NUMA、频率、数据库或下游限制,确认应用能否并行。

二十、监控与上线清单

  • [ ] 每核user/system/iowait/softirq/steal受监控;
  • [ ] Load与运行队列按CPU数量解释;
  • [ ] 上下文切换、线程数和迁移有基线;
  • [ ] PSI、Cgroup节流和容器limit可见;
  • [ ] IRQ、网卡队列和NUMA拓扑合理;
  • [ ] CPU频率、温度和功耗限制受监控;
  • [ ] 语言运行时Profile工具已准备;
  • [ ] perf采样和符号访问有安全边界;
  • [ ] 高CPU、D状态、Steal和quota场景有Runbook;
  • [ ] 调优前后以业务吞吐和P99验证。

二十一、结语

CPU性能分析不能停留在top截图。要把利用率、运行队列、调度等待、上下文切换、软中断、Cgroup和语言运行时联系起来。先确定时间花在计算、排队还是等待,再选择扩容、限流、绑核、算法优化或修复下游,才能真正改善业务延迟。

参考资料

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-10-29 20:20:35

results matching ""

    No results matching ""