什么是线程级排查
进程内部由多个线程(LWP)并行执行,只看进程级 CPU 占用无法定位热点,需要按线程维度观察。ps 的 -L 选项会为每个线程输出一行(LWP 列即线程 ID),top -H 把线程当作独立任务展示,perf 也可以只在某个线程上采样。内核为每个线程在 /proc/<pid>/task/ 下维护目录,这是在进程与线程之间对应关系上做进一步分析的基础。
基本信息
| 线程列表 | ps -eLf(LWP 列为线程 ID) |
|---|---|
| 按线程看 top | top -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)都有开销,高负载服务上应短窗口采集,并避免在故障恢复的关键时刻同时挂多个工具。
线程数突增常见于连接池或定时任务实现不当:把线程数与业务请求量放在一起对比,能较快判断是负载上升带来的,还是资源没有被正确释放。