本页目录
perf 很强,但它不是默认起手工具
第 13 章先把 perf 放回正确位置。它最擅长的,是 CPU 视角下的热点、调用栈和硬件事件。
如果问题还没缩小到这一层,perf 很容易给你一张很漂亮、但解释链并没有闭合的图。
perf 最适合回答什么
下面这些问题,更适合让 perf 上场:
- CPU 时间主要花在哪
- 哪段调用栈最热
- 某类硬件事件是不是异常集中
- on-CPU 视角下最值得继续看的代码路径是什么
这类问题里,perf 的价值很高。
perf 最不适合直接回答什么
下面这些问题,perf 通常不够:
- 线程到底在等什么
- 完整请求路径是怎么走的
- 因果链是怎么连起来的
- 某段等待为什么形成
如果你拿 perf 去直接回答这些问题,结论很容易飘。
别把热点直接当根因,也别让火焰图替你收口结论
最常见的错法有四种:
- 火焰图一出来,就直接宣布根因
- 把 on-CPU 样本当成整体时间分布
- 明明问题更像等待,还继续死磕 perf
- 已经知道 perf 解释不动了,还不愿意换工具
这些错法都把“热点”直接翻译成“根因”。
什么时候该停下 perf,换别的证据
出现下面这些情况时,继续深挖 perf 的收益通常已经不高:
- 你已经知道哪里热了,但不知道为什么慢
- 你怀疑主要时间其实花在等待上
- 你需要的是请求路径和因果关系
- 热点和整体症状一直接不起来
这时候该换 tracing、off-CPU 证据或更细的路径证据。
一个最典型的错法:火焰图很好看,但会议还在原地打转
现场里很常见:perf 跑完,火焰图也有了,热点函数也能点出来,结果会议里的争论一点没少。
这通常说明现在缺的不是“更细的热点”,而是别的证据:
- 等待证据
- 请求路径证据
- 前后对照证据
如果还留在 perf 里打转,只会越来越像在看漂亮图。
先把热点、问题链和停手点写清
先写清 perf 只回答哪三类问题
以后上 perf 前,先确认自己问的是不是这三类:
- CPU 时间花在哪。
- 哪段调用栈最热。
- 哪类硬件事件异常集中。
如果问的不是这三类,先别急着上。
真正落命令时,还要死守一条顺序底线:先 perf stat,后 perf record。perf record 会疯狂往 perf.data 落盘,本身就可能制造巨大的存储 I/O 干扰;先用开销更低的 perf stat 摸清事件频率,才能判断后面的采样值不值得做。
热点接不上整体症状时,就及时换证据
一旦出现“热点很清楚,但解释不动整体慢”,就别继续往火焰图里钻。先换路径、等待或因果链证据。
如果你已经落到了 PMC 级别的硬件事件,还要再防一种更隐蔽的假热点:指令滑移(skid)。不带精确修饰符去抓底层事件,样本地址很可能会往后漂,最后把完全无关的下游代码点成热点;这类场景至少要考虑 cycles:ppp 这类更精确的事件修饰。
perf 结果默认先当缩小方向,不当最终结论
perf 最稳的用法,是先缩小方向,再决定后面补什么,不是直接拿它当裁判。
火焰图回答不动时,再看内核路径
第 13 章解决的是“perf 该回答什么”。第 14 章接着解决“当问题已经落到内核路径里时,Ftrace 该怎么上场”。