性能排查与高CPU

6 阅读5分钟

1:top 的输出你平时都看哪几行?

考察点:top 全局观 · 会不会"分层看"

top - 10:24:31 up 12 days,  3:15,  2 users,  load average: 0.52, 0.58, 0.59
Tasks: 231 total,   1 running, 229 sleeping,   1 stopped,   0 zombie
%Cpu(s):  3.2 us,  1.5 sy,  0.0 ni, 94.0 id,  1.2 wa,  0.0 hi,  0.1 si,  0.0 st
MiB Mem :  15884.0 total,   1120.5 free,   6234.2 used,   8529.3 buff/cache
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.   8890.1 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   1234 root      20   0  2130000 450000  12000 S  45.3   2.8  120:31.22 java
行看什么
第一行时间、开机多久、load average(1/5/15 分钟平均负载)
第二行进程总数 / 运行中 / 睡眠 / 停止 / 僵尸
第三行CPU 8 个字段(本章重点)
第四行物理内存:total / free / used / buff/cache / available
第五行swap 使用情况
表头%CPU %MEM RES(实际内存)TIME+(累计 CPU 时间)S(进程状态)

2:top 里 CPU 这些字段分别是什么?

字段含义高的时候说明什么怎么查下去
us用户态 CPU 时间(普通用户进程)应用自己在算:死循环、复杂计算、正则、频繁 GCtop -H -p <pid> 找线程;Java jstack
sy内核态 CPU 时间(执行内核代码)系统调用 / 上下文切换太频繁:IO 切换、进程线程太多、锁竞争vmstat 1 看 cs;pidstat -w;strace -c
ni低优先级(nice 值)进程占的 CPU有人调低了优先级在跑重活(和 us 本质相同,单独统计便于区分)ps -eo pid,ni,pcpu,cmd --sort=-ni
id空闲高就是 CPU 闲(100 − id 约等于总使用率)—
wa等 IO 的时间(CPU 空闲但有 IO 未完成)磁盘 / 网络存储是瓶颈,不是 CPU 忙iostat -x 1 看 %util、await
hi硬中断(硬件中断处理)网卡收包太猛(大量小包、DDoS)、磁盘中断/proc/interrupts;mpstat -P ALL 1
si软中断(内核协议栈处理)网络流量大(大量连接 / 高吞吐),常和 hi 一起高/proc/softnet_stat;ksoftirqd 线程 CPU
st被宿主机"偷走"的时间虚拟机 / 云主机超卖:你想跑但宿主机没给你 CPU联系云厂商;查宿主机负载

★ 记忆法(背这一句):「us 是应用在算,sy 是内核在忙,wa 是在等盘,ni 是低优先级,hi/si 是网卡,st 是别人抢走了,id 是闲着。」

必记的判断逻辑:

CPU 真忙    :us / sy 高,id 低        → 找进程、找线程、看是不是计算型
IO 瓶颈     :wa 高,us 不高            → 加 CPU 没用,要看磁盘(iostat)
网络瓶颈    :hi / si 高                → 看网卡、看连接数、看是不是被攻击
超卖        :st 高                     → 云主机 / 虚拟机,宿主机资源不够
ni 高                                  → 有人在 nice 调低优先级跑批处理

3:top 里有哪些交互键是你会用的?

按键作用
P按 CPU 排序(默认)
M按内存排序
T按累计 CPU 时间排序
1展开每个核的使用率(多核机器排查必用)
H显示线程(等价于 top -H)
c显示完整命令行(看到启动参数)
k在界面里杀进程
rrenice(调整优先级)
z彩色高亮
W把当前配置写成 ~/.toprc
q退出

4:load average 三个数字是什么意思?多少算高?

考察点:load 的定义 · 和核数的关系 · "load 高 CPU 低"这个经典陷阱

load average = 过去 1 / 5 / 15 分钟,平均有多少个"任务"在排队。
任务 = 正在跑 + 等 CPU 的可运行进程 + 不可中断睡眠(D 状态,等 IO)的进程

判断标准:和"核数"比,不是和 100% 比
  load ≈ 核数        → 差不多跑满
  load > 核数        → 开始排队,响应变慢
  load >> 核数       → 严重排队(经验值:超过核数 2 倍要处理)
nproc                       # 看几个核(★ 不要凭感觉)
uptime                      # 看 1/5/15 分钟负载
cat /proc/loadavg           # 负载 + 当前可运行数/总进程数
vmstat 1 5                  # r = 运行队列,b = 阻塞(D 状态)进程数

1 / 5 / 15 怎么配合看:

15 分钟低、1 分钟高  → 刚刚飙起来的(突发流量 / 刚发布 / 定时任务)
1 分钟低、15 分钟高  → 之前高过,现在在恢复
三个都高             → 持续性的容量不足,该扩容了

5:load 很高,但 CPU 使用率很低,为什么?

考察点:load 包含 D 状态

原因怎么确认
磁盘 / 网络 IO 卡住,大量进程处于 D 状态vmstat 的 b 很大、wa 高、iostat 的 %util 高
内存不足在换页vmstat 的 si/so 非 0
进程被 cgroup 限流(容器 CPU quota 用满)cat /sys/fs/cgroup/.../cpu.stat、容器被 throttle
宿主机超卖(虚拟机 st 高)top 里的 st

「load 统计的是运行队列 + D 状态的进程,所以 IO 卡住、换页、被限流都会让 load 升高但 CPU 不高。这时候要看 vmstat 的 r/b/wa/si/so 去区分到底是 CPU 排队还是 IO 排队。」


6:vmstat 和 iostat 各看什么?

vmstat 1(CPU + 内存 + IO 综合):

列看什么
r运行队列长度(大于核数说明 CPU 排队)
b阻塞进程数(多是 D 状态、等 IO)
si / so换入 / 换出速率(内存压力)
bi / bo块设备读入 / 写出(IO 量)
cs上下文切换次数
us sy id wa和 top 第三行一样

iostat -x 1(磁盘 IO):

列看什么
%util设备忙的时间占比,接近 100% 说明磁盘是瓶颈
await平均等待时间(明显变大 = 排队严重)
r/s w/s每秒读写次数(IOPS)
rkB/s wkB/s每秒读写吞吐

上下文切换(和 sy 高配套):

vmstat 1 5              # cs 列 = 每秒上下文切换次数
pidstat -w 1            # 每个进程的自愿/非自愿切换
pidstat -w -t -p <PID>  # 线程级
概念说明
自愿切换进程主动让出 CPU(等 IO、sleep)
非自愿切换时间片用完被抢占 / 被更高优先级抢占 → 多了说明线程太多或锁竞争
经验值cs 上万且 sy 高,基本可以判断是"系统调用 / 切换开销大"

常用性能工具一览(面试问"你平时用什么工具"):

看什么工具
CPUtop / vmstat / mpstat / sar
内存free / vmstat / smem
磁盘iostat / iotop / pidstat -d
网络ss / sar -n DEV / tcpdump
按进程/线程pidstat / top -H / ps -L
找热点perf top / 火焰图
系统调用strace -c / ltrace