perf 调用栈采集方式

-g 搭配 fp 或 dwarf 采集调用链, 决定火焰图与归因的可用深度。

调用栈采集方式

调用栈的采集方式决定了报告与火焰图能下钻到多深。基于帧指针的方式靠遍历栈帧还原调用链,开销低,但要求二进制保留帧指针;基于调试信息展开的方式逐帧解析,覆盖更完整,但记录的数据量显著更大;基于硬件分支记录的方式受记录深度限制。选错方式会得到断层的调用栈。

基本信息

适用平台Linux(采集与报告由同一工具链完成)
选项含义指定调用栈采集方式
帧指针方式开销低,依赖二进制保留帧指针
调试信息方式覆盖更全,输出文件更大
分支记录方式依赖硬件支持且有深度限制

典型使用场景

  • 火焰图出现断层时确认采集方式是否匹配程序编译选项。
  • 发行版二进制默认省略帧指针,导致调用栈不完整。
  • 深调用栈服务采集前评估输出文件大小与磁盘余量。
  • 定位被内联展开的函数归属,判断优化对象。
  • 对比两种采集方式在同一负载下的差异,选择更合适的方案。

用法

用法
perf record -F 99 -g --call-graph dwarf -p 12345 -- sleep 20   # 用调试信息展开调用栈
perf record -F 99 -g --call-graph fp -a -- sleep 20            # 帧指针方式,开销更低
perf report --stdio --sort symbol | head -30                    # 检查是否还有断层与地址
perf record --call-graph dwarf,8192 -p 12345 -- sleep 10        # 加大栈拷贝尺寸,覆盖深栈
ls -lh perf.data                                               # 采集前先估算磁盘占用

三种方式对比

方式开销与数据量适用情况
帧指针开销低、数据量小二进制保留了帧指针的自家程序
调试信息开销与数据量较大发行版二进制或栈较深的程序
分支记录硬件相关、深度有限需要低开销短栈归因
自研程序在编译时保留帧指针可以显著降低采集成本;用发行版二进制做分析时,多数情况需要走调试信息展开这条路。
深栈加高频率采样会生成非常大的数据文件,采集前先估算磁盘占用并控制窗口时长,否则可能影响被观测服务本身。

易错点

  • 发行版编译器默认省略帧指针,用帧指针方式得到残缺调用栈,火焰图断层难以解读。
  • 未评估数据量就长时间高频采集,文件撑爆磁盘或影响业务。
  • 栈拷贝尺寸偏小:深栈场景下更上层调用被截断,归因停在中间层。
  • 不看采集方式就在不同机器之间对比火焰图,形状差异来自方法而非程序。
  • 把缺少符号与调用栈断层混为一谈:一个是符号解析问题,一个是采集方式问题。

数据来源与参考

  • man perf-record
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌