You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让perf识别Go程序中的函数符号?

解决Perf无法识别Go程序符号的问题

核心问题分析

Go的goroutine调度、异步抢占等运行时机制,加上默认编译特性,会导致Perf默认的符号解析逻辑失效——即便你已经通过-N -l关闭了代码优化和内联。以下是针对性的解决方案:


1. 确保Perf版本兼容

Perf对Go符号的支持在Linux 5.10及以上版本有明显改进,老版本可能无法正确解析Go的调用栈和符号。先检查版本:

perf --version

若版本过低,建议升级内核或Perf工具。

2. 编译时保留完整符号表并优化解析兼容性

除-N -l外,需确保编译时不剥离符号表,并根据Go版本调整参数:

  • Go 1.14~1.20版本:启用frame pointer(让Perf能通过标准栈指针解析调用栈)
    GODEBUG=asyncpreemptoff=1 go build -gcflags=all="-N -l" -ldflags="-s=false" -o my_program ./*.go
    
    说明:-s=false确保不剥离符号表;asyncpreemptoff=1关闭Go异步抢占,强制使用frame pointer。
  • Go 1.21+版本:AMD64架构默认启用frame pointer,直接编译即可:
    go build -gcflags=all="-N -l" -o my_program ./*.go
    

3. 使用正确的Perf采样命令

必须指定调用栈解析方式,否则Perf无法识别Go函数:

perf record -F 99 -g --call-graph dwarf ./my_program
  • -F 99:设置采样频率(避免过高导致性能开销)
  • -g:记录调用栈信息
  • --call-graph dwarf:用DWARF调试信息解析栈帧,适配Go运行时栈结构

4. 手动指定符号表路径(若仍无法解析)

如果Perf还是找不到符号,可在分析时显式指定可执行文件路径:

  • 查看报告时:
    perf report -i perf.data --symfs ./
    
  • 生成火焰图时(确保当前目录存在my_program):
    perf script -i perf.data | ./stackcollapse-perf.pl | ./flamegraph.pl > flame.svg
    
    或直接指定符号文件:
    perf script -i perf.data -d ./my_program | ./stackcollapse-perf.pl | ./flamegraph.pl > flame.svg
    

5. 排查系统安全限制

SELinux或AppArmor可能阻止Perf访问进程内存,导致符号解析失败:

  • 临时关闭SELinux(仅测试用):
    sudo setenforce 0
    
  • 检查AppArmor对Perf的限制:
    sudo aa-status
    

关于go build -toolexec="perf record"的说明

该参数作用是让Go工具链(如编译器)执行时被Perf记录,而非记录你编译出的my_program运行状态,因此对你的场景完全无效,直接忽略即可。


内容的提问来源于stack exchange,提问作者Yu-Ang Cao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:56:18