pidstat -p pid -u 1可实时监控进程的%usr(用户态cpu占比)和%system(内核态cpu占比),前者反映业务逻辑开销,后者揭示系统调用、锁争用或驱动问题;加-t参数可展开线程级视图,结合jstack等工具定位热点线程。

直接用 pidstat -p PID -u 1 就能实时看到该进程的 %usr(用户态)和 %system(内核态)CPU 占比,这是定位性能瓶颈的关键分水岭——高 %usr 通常指向业务逻辑或算法问题,高 %system 则暗示系统调用频繁、锁争用或驱动层开销。
看懂两个核心字段的含义
%usr 表示进程在用户空间执行代码所占用的 CPU 时间比例,比如 Java 应用做字符串处理、Python 脚本解析 JSON;%system 是进程陷入内核执行系统调用(如 read/write/mmap/futex)所占的 CPU 时间。两者加起来接近 %CPU,但不等于 100%,因为还有 %guest(虚拟机开销)和调度空闲时间。
结合线程级视角定位热点
单个进程可能有多个线程,而 %usr/%system 是按进程汇总的,容易掩盖问题。加 -t 参数展开线程视图:
-
pidstat -p PID -u -t 1:每秒输出一次,显示每个线程的 TID、%usr、%system 和所属 CPU - 若发现某个 TID 的 %system 明显高于其他线程,大概率在等锁(如 pthread_mutex 或 futex)、做大量 syscalls(如 epoll_wait + writev 组合),或触发了高频中断处理
- 对 Java 进程,可进一步用
jstack PID | grep 'nid=0x[0-9a-f]\+.*runnable'匹配高 %system 的 TID(注意十六进制转换),查具体栈帧
区分真实负载与瞬时抖动
%usr 和 %system 是采样周期内的平均值,短生命周期线程可能被漏掉。建议:
- 用较短间隔(如
0.5或0.2)捕获突刺行为,避免因采样窗口太宽而平滑掉峰值 - 连续观察 10–30 秒,关注趋势而非单次数值;若 %system 持续 >30%,且伴随高 nvcswch/s(非自愿切换),基本可判定存在锁竞争或 CPU 资源不足
- 对比
top -p PID中的 “%CPU” 字段——它默认是自启动累计值,而 pidstat 是滚动平均,二者数值差异属正常现象
排除干扰因素
某些场景下 %system 偏高并非异常:
- 使用 mmap + madvise(POSIX_MADV_DONTNEED) 频繁释放内存页,会触发内核页表操作
- 开启透明大页(THP)后,首次访问大页会引发内核分配和映射,带来短暂 %system 上升
- 容器环境下,cgroup 限频或 CPU quota 超限时,进程会被内核强制节流,表现为 %system 升高但实际没干活











