登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  Golang >  Go教程

Go go tool pprof 怎样切换采样指标查看内存

来源:17golang原创

时间:2026-10-26 17:21:45 403浏览 收藏

我第一次用 go tool pprof 看 Go 内存问题时,最容易误判的不是函数名,而是“数字到底代表什么”。同一个 profile 里可能同时保存已占用空间、已占用对象数、累计分配空间和累计分配对象数。如果不切换采样指标,top 输出看起来完整,结论却可能答非所问。

这篇只解决一个动作:怎样在 go tool pprof 中切换采样指标查看内存。最稳妥的做法是先让 pprof 告诉你当前 profile 有哪些采样值,再用采样值名称选择口径;需要自动化时,再把同一个名称写进命令行参数。

官方资料:https://go.dev/doc/diagnostics

先确认 profile 里的采样值

sample_index 选择的不是“第几行函数”,而是每个 sample 中的第几个数值。pprof 的 profile 可以为同一组调用栈保存多个数值,选中的数值会成为后续报告的统计口径。

例如,你已经拿到内存 profile,可以先进入交互模式:

# 读取已有的内存 profile;这里仅展示用法,不代表已在本机执行
go tool pprof mem.prof

在 pprof 提示符中输入:

# 先查看当前 profile 可选择的采样指标
(pprof) sample_index

# 也可以查看交互命令和选项说明
(pprof) help

内存 profile 常见的采样值包括 inuse_space、inuse_objects、alloc_space 和 alloc_objects。实际可选项仍以当前 profile 的 SampleType 为准,不能假设任何 profile 都有完整的四项。

pprof 内存 profile、SampleType、sample_index 与四种内存采样值的静态关系图
图1:pprof 内存 profile 的采样值选择关系说明图,不是运行截图或运行证据。

在交互模式切换指标

确定名称后,直接给 sample_index 赋值即可。比如想看当前仍然存活的内存空间:

# 选择仍在使用的内存字节数作为报告口径
(pprof) sample_index = inuse_space

# 按新的口径重新查看热点函数
(pprof) top

如果关心的是对象数量,可以切换到:

# 选择仍在使用的对象数量,而不是对象占用的字节数
(pprof) sample_index = inuse_objects

# 重新生成文本热点列表
(pprof) top

这里有一个容易忽略的点:切换指标只改变报告使用的采样值,不会改变 profile 本身,也不会重新采集数据。因此,切换之后看到的函数排序可能变化,但它们仍来自同一份输入 profile。

用命令行参数固定同一口径

如果报告要放进脚本、排障记录或 CI 流程,不建议依赖交互式输入。可以把 -sample_index 写到启动命令中:

# 用存活内存空间生成文本报告,名称比数字索引更容易复查
go tool pprof -sample_index=inuse_space -top ./app mem.prof

# 用累计分配空间生成另一份报告,用于观察分配总量
go tool pprof -sample_index=alloc_space -top ./app mem.prof

命令中的 ./app 用于帮助 pprof 做符号化,mem.prof 是 profile 输入。若 profile 本身已经带有足够的符号信息,输入程序的作用仍然是让源码和函数定位更完整;它不是采样指标的来源。

也可以只启动交互模式,但预先固定指标:

# 进入交互模式时先固定累计对象数口径
go tool pprof -sample_index=alloc_objects ./app mem.prof

进入后再执行 top、list 函数名 或其他报告命令,都会沿用这个选择。

分清 inuse 与 alloc、space 与 objects

我在排查“服务当前占用太高”和“某段代码分配过于频繁”时,会先把指标分成两个维度:inuse 或 alloc 表示时间语义,space 或 objects 表示计量单位。

指标它回答的问题更适合观察
inuse_space当前仍被占用多少字节存活内存、疑似泄漏、驻留体积
inuse_objects当前仍有多少对象对象数量膨胀、细小对象堆积
alloc_space累计分配过多少字节分配总量、分配热点、短命对象制造
alloc_objects累计分配过多少对象分配次数、对象创建频率
inuse、alloc、space、objects 四种 pprof 内存指标的语义分组关系图
图2:四种内存采样指标的语义边界与适用问题示意图,不是运行截图或运行证据。

两个维度组合起来就比较清楚了:inuse_space 偏向回答“现在还占着多少内存”,alloc_space 偏向回答“到目前为止分配过多少内存”。前者适合定位驻留问题,后者适合寻找高频分配路径;两者不能互相替代。

处理索引、profile 类型和空结果边界

sample_index 的数字索引从 0 开始。虽然可以写成 -sample_index=1 或在交互模式中写数字,但我更推荐写指标名称:名称直接表达语义,也不容易因为 profile 的采样值顺序变化而误读。

# 数字索引从 0 开始;只有确认当前 profile 顺序时才这样写
(pprof) sample_index = 0

# 推荐用名称表达目标指标,便于复查和脚本维护
(pprof) sample_index = alloc_space

如果名称不存在,或者索引超出当前 profile 的范围,pprof 会给出错误提示。此时不要把错误理解成“程序没有内存数据”,先回到 sample_index 查看实际选项。profile 类型也会影响可用指标:CPU、goroutine、block、mutex 等 profile 的采样值语义不同,不能拿内存指标名称强行套用。

Go 官方诊断文档还提醒,不同 profiling 工具可能互相影响精度;排查内存时尽量先单独收集目标 profile。sample_index 只是读取和选择已有数据的方式,不会替代采集阶段,也不会把一次错误的采集变成可靠数据。

我通常这样做最后判断

  1. 先用 sample_index 确认当前 profile 提供哪些采样值。
  2. 排查当前占用时优先从 inuse_space 或 inuse_objects 开始。
  3. 排查分配行为时切到 alloc_space 或 alloc_objects。
  4. 对比报告或自动化脚本使用 -sample_index=指标名,避免只记录数字索引。
  5. 看到异常结果时,先确认 profile 类型和指标语义,再判断代码是否真的存在问题。

常见问题

sample_index 能不能直接改变 heap profile 的采集内容?

不能。它只是在已有 profile 的多个采样值中选择报告口径;采集阶段没有记录的指标,切换时也不会凭空产生。

为什么切换到 alloc_space 后,热点函数和 inuse_space 不一样?

两者回答的时间问题不同。一个强调当前仍存活的空间,一个强调累计分配的空间,短命对象会明显影响后者。

数字索引和指标名称哪个更好?

临时探索时数字索引可以使用;要写进脚本、文档或复盘记录时,指标名称更直观,也更不容易因顺序记错而得到错误结论。

总结

用 go tool pprof 查看内存时,关键不是反复执行 top,而是先选对采样指标。交互模式用 sample_index = inuse_space 这样的名称切换,自动化场景用 -sample_index=inuse_space 固定口径;再根据 inuse/alloc 与 space/objects 的组合解释结果,就能把“当前占用”和“累计分配”分开看。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>