go tool pprof 本身不生成火焰图,必须用 -raw -lines 导出折叠栈文本,再经 flamegraph.pl 渲染为 svg;-svg 参数调用 dot 输出的是调用图而非火焰图,web 界面的 /ui/flamegraph 路径虽存在但依赖 perl 和 flamegraph.pl,易因环境缺失失败。

go tool pprof 本身不导出火焰图,它只负责采样和解析;真正生成 SVG 火焰图必须经过「折叠栈文本 + flamegraph.pl」两步,跳过任何一环都会得到空白、扁平或全是 runtime.mcall 的无效图。
为什么直接 go tool pprof -svg 不是火焰图
-svg 参数调用的是 dot 工具,输出的是调用图(callgraph),不是火焰图(flame graph)。两者结构完全不同:callgraph 展示函数间调用关系,flame graph 展示时间维度上的调用栈分布。很多用户点开 Web UI 后找不到“Flame Graph”按钮,其实是因为默认界面压根不提供该入口——它只在 /ui/flamegraph 路径下存在,且底层仍依赖 Perl 和 flamegraph.pl。
常见错误现象:
- 执行
go tool pprof -svg cpu.pprof后报错failed to execute dot,或生成一个巨大、无法缩放、节点重叠的图 - Web 界面点“Flame graph”按钮无反应,控制台静默失败
- 生成的 SVG 里函数名全是
?或[unknown]
go tool pprof -raw -lines 是导出火焰图的唯一可靠路径
这组参数组合是生成可渲染火焰图的最小必要条件:-raw 输出原始采样栈(非协议缓冲格式),-lines 强制展开行号信息,确保 flamegraph.pl 能正确折叠并保留业务代码层级。
实操建议:
- 用
go tool pprof -raw -lines http://localhost:6060/debug/pprof/profile?seconds=10 > stacks.txt导出文本(别用> cpu.pprof) - 若采样的是本地文件(如
cpu.pprof),必须同时传入二进制路径:go tool pprof -raw -lines ./myapp cpu.pprof > stacks.txt,否则符号无法还原 - 别用
curl直接下载二进制.pprof文件再喂给pprof—— HTTP 接口返回的是协议缓冲格式,而-raw模式只接受已解析的栈文本
火焰图里全是 runtime.mcall 或 [unknown] 怎么办
这不是 pprof 工具的问题,而是符号表缺失或编译优化干扰导致的还原失败。火焰图底部堆满系统调用,说明业务代码根本没被采到。
关键修复点:
- 编译时去掉 strip:用
go build -ldflags="" main.go,禁用-s -w - 关闭内联和优化以保全调用栈语义:
go build -gcflags="-l -N" main.go - Linux 上检查
/proc/sys/kernel/perf_event_paranoid是否 ≤ 2;否则内核拒绝 perf 采样,pprof只能 fallback 到低精度信号采样 - 容器环境要显式加
--cap-add=SYS_ADMIN,否则同样触发权限限制
Web UI 的 /ui/flamegraph 路径怎么用才不翻车
这个路径确实存在,但非常脆弱:它要求本地装了 Perl、flamegraph.pl 在 PATH、且 PPROF_BINARY_PATH 指向正确的二进制(用于符号化)。稍有缺失就白屏或 500。
更现实的做法:
- 启动服务时加
-http=:8080,然后手动访问http://localhost:8080/ui/flamegraph - 如果报
exec: "perl": executable file not found,立刻切回命令行流程,别折腾环境 - 该页面不支持 zoom,SVG 导出后也无法交互;真要分析,不如本地生成
flame.svg用浏览器打开,Ctrl+滚轮自由缩放
runtime.futex 可能是 GC STW、goroutine 频繁调度,而非锁竞争;syscall.Syscall 堆积未必是 I/O 慢,可能是 context deadline 触发重试风暴。这时候得交叉比对 go tool trace 的 goroutine 分析视图,否则优化方向很容易跑偏。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











