首页/系统/Linux 内核与性能调优速查/线程级排查:ps -eLf / top -H
CPU 与调度60 条

线程级排查:ps -eLf / top -H

按线程维度观察 CPU 占用:ps 用 LWP 列、top -H 显示线程;定位热点线程后再用 perf 等工具深挖。

什么是线程级排查

进程内部由多个线程(LWP)并行执行,只看进程级 CPU 占用无法定位热点,需要按线程维度观察。ps 的 -L 选项会为每个线程输出一行(LWP 列即线程 ID),top -H 把线程当作独立任务展示,perf 也可以只在某个线程上采样。内核为每个线程在 /proc/<pid>/task/ 下维护目录,这是在进程与线程之间对应关系上做进一步分析的基础。

基本信息

线程列表ps -eLf(LWP 列为线程 ID)
按线程看 toptop -H -p <pid>
指定线程分析perf top -t <tid>
内核视图/proc/<pid>/task/<tid>/
相关指标TID、PSR(所在 CPU)、%CPU、STAT 状态
适用多线程服务、JVM 与 Go 程序的热点定位

典型使用场景

  • CPU 占用高但进程级看不出原因:下钻到线程找热点
  • 线程数异常增长:判断是否有线程泄漏
  • 定位线程亲和性:观察 PSR 列是否集中在个别 CPU
  • 配合 perf/jstack 做热点归因(Go 用 pprof、Java 用 jstack)
  • 排查锁竞争:结合 STAT 状态看线程是否长期处于睡眠或等待

常用命令

常用命令
ps -eLf | head -5                        # 全系统线程视图,注意 LWP 列
ps -L -o pid,tid,psr,pcpu,stat,comm -p 12345   # 只看某进程的线程
ps -eLf | awk 'NR==1 || $2==12345'       # 过滤某个进程的线程
top -H -p 12345                          # 交互式按线程看 CPU
cat /proc/12345/status | grep -i threads # 线程总数
ls /proc/12345/task | wc -l              # 与上面的数字互相校验
perf top -t <tid>                        # 对指定线程采样

输出逐列读法

列/字段含义异常信号
LWP线程 ID(TID)与 PID 不同的命名空间,工具附加时要用它
PSR线程所在 CPU长期集中在单核说明没有分散
%CPU线程级占用单个线程接近 100% 即单核打满
STAT线程状态长期 R 或 D 状态需进一步排查
Threads进程线程总数持续增长提示线程泄漏
JVM 与 Go 这类运行时会创建大量线程(GC、工作线程),线程数本身不是问题;判断依据是热点分布与增长趋势,而不是绝对数量。
在线程上附加采样工具(perf、strace)都有开销,高负载服务上应短窗口采集,并避免在故障恢复的关键时刻同时挂多个工具。
线程数突增常见于连接池或定时任务实现不当:把线程数与业务请求量放在一起对比,能较快判断是负载上升带来的,还是资源没有被正确释放。

易错点

  • TID 与进程 PID 不同名空间:perf/strace 附加线程要用 TID,用 PID 会定位到错误对象
  • 线程退出后其 TID 消失,采样要覆盖足够时间窗口,一两次快照可能完全抓不到热点
  • 只看进程级 %CPU 就下结论,多线程程序里真正的瓶颈可能是某个单线程热点
  • 在运行时线程数很多时按数量判断故障,忽略了 GC 与工作线程本来就多的正常情况

数据来源与参考

  • procps-ng 文档 ps(1)/top(1)
  • Linux 内核 /proc/<pid>/task 接口
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌