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 名称映射的讨论。