真实面经题目 · 原创解析
常见的cpu load过高,us过高,一般是什么问题?
CPU load 高和 CPU 使用率高不是同一个概念。load average 统计可运行队列和不可中断 I/O 任务,us 高表示用户态代码消耗大量 CPU。排查要先看 us、sy、wa、si、st 的结构,再定位到进程、线程和调用栈。
真实面经题目 · 原创解析
CPU load 高和 CPU 使用率高不是同一个概念。load average 统计可运行队列和不可中断 I/O 任务,us 高表示用户态代码消耗大量 CPU。排查要先看 us、sy、wa、si、st 的结构,再定位到进程、线程和调用栈。
我会先区分 load average 和 CPU usage。load average 表示一段时间内处于可运行状态或不可中断 I/O 状态的任务平均数,要和 CPU 核数一起看;CPU usage 表示 CPU 时间分布,常见字段有 us、sy、wa、si、st。常见的 load 高且 us 高,通常说明大量线程真的在用户态跑 CPU,原因可能是热点算法、死循环、自旋、线程池过大、频繁 GC、序列化反序列化、正则回溯、压缩、加解密等。排查路径是先用 uptime 看 1、5、15 分钟趋势并和核数比较,再用 top 看整体 CPU 构成和高 CPU 进程,用 vmstat 看 r 队列、b 队列、上下文切换和中断,用 pidstat 或 top -H 定位到进程和线程。Java 服务还要把线程 id 转成十六进制,对应到 jstack 的 nid 找具体栈;native 或混合场景可以继续用 perf 定位热点函数。如果 wa 高,优先查磁盘、数据库或网络存储;如果 sy 高,查系统调用、锁竞争和上下文切换;如果 si 高,查网络软中断;如果 st 高,查虚拟化资源抢占。
load average 不是 CPU 使用率,而是平均活跃任务数,包含正在运行、等待 CPU 运行和不可中断 I/O 的任务。CPU usage 则是 CPU 时间花在哪里的比例。面试中先把这两个概念分开,能避免把所有 load 高都误判成 CPU 算力不够。
us 表示用户态 CPU 时间。us 高通常说明应用代码本身在消耗 CPU,常见原因包括死循环、复杂算法、正则灾难回溯、JSON 序列化、压缩、加解密、频繁 GC、线程自旋、线程池过大导致大量可运行线程争抢 CPU。
sy 高偏向内核态开销,常见于系统调用密集、锁竞争、上下文切换过多、网络或文件操作频繁。wa 高说明 CPU 等 I/O,可能是磁盘、数据库、网络存储慢。si 高偏网络软中断或包处理压力,st 高说明虚拟机 CPU 被宿主机抢占。
vmstat 中 r 表示等待或正在运行的任务数,长期大于 CPU 核数通常说明 CPU 排队严重;b 表示不可中断睡眠任务,b 高通常和 I/O 阻塞有关。load 高时结合 r 和 b,才能判断是 CPU 密集还是 I/O 堆积。
基础路径是 uptime 看趋势,top 看 CPU 构成和进程,vmstat 看 r、b、cs、in,pidstat 看进程或线程级 CPU。Java 场景用 top -H 找高 CPU 线程,将线程 id 转十六进制后在 jstack 中匹配 nid,再分析具体代码栈。
如果定位到业务热点,要优化算法、减少重复计算、控制批量大小或缓存结果;如果是 GC,要看堆、分配速率和对象生命周期;如果是线程池,要调整并发度和队列策略。不能只凭 load 高就扩容,否则可能掩盖根因。
常见是不可中断 I/O 任务堆积,例如磁盘慢、网络存储慢、数据库响应慢、文件系统阻塞。此时 vmstat 的 b 和 iostat、磁盘延迟指标会比单看 top 更关键。
us 高说明应用用户态逻辑重,sy 高说明内核态开销重。可以结合 perf、strace、上下文切换、系统调用频率、锁竞争和网络包量来判断是业务计算还是内核路径消耗。
先用 top -H 或 pidstat 找到高 CPU 线程,再把十进制线程 id 转为十六进制,在 jstack 输出里按 nid 查找对应线程栈,最后结合多次采样判断稳定热点。
大量线程处于可运行状态会增加运行队列长度,也会带来调度、上下文切换和锁竞争成本。即使每个线程做的事不重,总体也可能把 CPU 时间消耗在争抢和切换上。