剖析与火焰图怎么用
性能剖析用采样方式记录调用栈:在代表性负载下隔一段时间抓一次栈,样本足够多之后,栈出现频率就近似反映各代码路径的资源占用。火焰图把这些样本横向展开——横轴宽度是样本占比,纵向是调用层次,因此一眼能看出“谁真正占用了 CPU”。它的价值在于把优化对象从猜测变成证据:先定位占比高的自身消耗,再决定改哪里。
基本信息
| 常见工具 | perf(Linux 内核采样)、async-profiler(JVM)、pprof(Go) |
|---|---|
| 维度 | CPU 热点、内存分配、锁竞争、IO 等待,一次聚焦一个 |
| 读图要点 | 找“自身占比高”的宽块,而不是只看顶部被调用的壳函数 |
| 前置条件 | 负载需可复现且贴近生产的数据规模与请求比例 |
典型使用场景
- CPU 使用率高但不知原因:定位具体函数与调用路径
- 接口延迟高而依赖正常:确认耗时是计算、序列化还是锁等待
- 内存分配频繁:按分配维度查看对象创建热点,减少临时对象
- 锁竞争排查:按锁维度查看等待栈,找出争用点
- 优化收益验证:改前改后同负载复采,对比火焰图形状变化
流程
流程
1. 确认场景可复现,采集代表性负载下的样本
2. 生成火焰图:宽度=样本占比,颜色区分维度
3. 找自身占比高的函数(而非被调用的壳函数)
4. 优化后复采对比,验证收益维度与判断
| 维度 | 能看到什么 | 常见结论方向 |
|---|---|---|
| CPU | 各调用栈占用 CPU 的比例 | 算法复杂度、重复计算、序列化开销 |
| 内存分配 | 对象分配的位置与数量 | 临时对象过多、集合无预设容量 |
| 锁 | 锁等待与竞争栈 | 临界区过大、共享结构粒度粗 |
| IO 等待 | 阻塞在读写上的比例 | 同步 IO、批量过小、连接复用不足 |
操作要点
- 准备代表性负载:请求比例与数据规模贴近生产,否则热点会失真
- 选择维度:CPU 热点、内存分配、锁竞争,一次聚焦一个
- 采样生成火焰图,自下而上找自身占用高的分支
- 定位函数后核对代码路径与调用频次,评估优化空间是否值得
- 修改后同负载复采,对比火焰图与指标变化,把有效优化固化成回归
采样剖析有观测误差,优化前后要用相同方法与负载复测,避免被噪声误导;单次对比的差异要大到能排除噪声才可采信。
在生产环境做高频采样会带来额外开销:采样频率、采样时长与目标进程的选择都要事先评估,必要时先在预发环境复现。