编程 Go 1.28 的 PGO 能吃 perf 采样了:perf_to_profile 转换与样本列匹配的坑

2026-11-03 21:01:18

Go 1.28 的 PGO:改用 perf 采集的 CPU profile,以及 FromPProf 选择哪一列作为样本

状态:Done。 用户可见的 FromPProf 现在接受来自 Linux perf 等外部工具采集的 CPU profile;这些 profile 要先经 perf_to_profile 转换(CL 3bd19c1c39,issue #64489)。当 value 名称与 Go 自身不一致时(例如 cycles_event / count),FromPProf 会取其中具有 CPU 采样特征的那一列作为样本权重。Left open: 暂无。

背景

Go 的 PGO 从 1.20 开始实验,1.21 起默认开启 -pgo=auto,读取 main 包的 default.pgo。

历史上 pprof 只接受 Go 自己的 runtime/pprof 采集的 profile 格式。Linux perf 的 perf.data 必须先用 perf_to_profile 转成 pprof 格式,但转出来的 profile 里 sample value 名字常是 cycles_event / count 之类,并非 Go 期望的 samples/cpu/nanoseconds。在 Go 1.28 之前,这种情况会因找不到对应 value 列而退化,甚至根本不使用该 profile。

1.28 中名称不匹配时选择哪一列

FromPProf 现在明确:value 名称与 Go 不一致时,选择那一列“具有 CPU 采样特征”的,用它的值作为样本权重,而不是因名字对不上就丢弃。外部 profile 的名称映射讨论记录在 issue #64489。

命令链

perf record -F 99 -g -o perf.data -- ./bin/app
perf script -i perf.data -F +pid,+period,+cpu,+callindent > perf.script
perf_to_profile -i perf.data -o cpu.pprof
go build -pgo=cpu.pprof ./cmd/app

转换不需要 go tool pprof,直接交给 perf_to_profile。perf_to_profile 需要在 tools 目录下用匹配版本的 perf 构建。

注意事项

  • -pgo 只接受单个文件路径或 auto/off,不能给目录。
  • 采样频率:perf 默认 -F 4000 太高,-F 99 适中;频率太低会让内联收益不稳定。
  • 在容器里运行 perf 需要 CAP_PERFMON,或把 perf_event_paranoid 调到 <= 2。
  • 内核符号缺失时,Go 用户态符号仍然可用,因为 Go 使用自己的帧指针/栈展开,profile 依然能派上用场。
  • 与 -pgo=auto 共存时,手写路径优先。

issue #64489 记录了外部 profile 名称映射的讨论。

复制全文 生成海报 Go 性能优化 profile

推荐文章

程序员茄子在线接单