为了账号安全,请及时绑定邮箱和手机立即绑定

Golang Alloc 和 HeapAlloc vs pprof 差异大

Golang Alloc 和 HeapAlloc vs pprof 差异大

Go
慕村225694 2023-06-19 15:16:46
我有一个 Go 程序可以计算内存中的大型相关矩阵。为此,我设置了一个包含 3 个 goroutine 的管道,第一个读取文件,第二个计算相关矩阵,最后一个将结果存储到磁盘。问题是,当我运行程序时,Go 运行时分配了大约 17GB 的内存,而矩阵只占用大约 2-3GB。使用runtime.ReadMemStats显示该程序正在使用 ~17GB(并使用 htop 验证),但pprof仅报告约 ~2.3GB。如果我在通过管道运行一个文件后查看内存统计信息:var mem runtime.MemStatsruntime.ReadMemStats(&mem)fmt.Printf("Total alloc: %d GB\n", mem.Alloc/1000/1000/1000)这显示了程序的总分配:Total alloc: 17 GB但是,如果我运行,go tool pprof mem.prof我会得到以下结果:(pprof) top5Showing nodes accounting for 2.21GB, 100% of 2.21GB totalShowing top 5 nodes out of 9      flat  flat%   sum%        cum   cum%    1.20GB 54.07% 54.07%     1.20GB 54.07%  dataset.(*Dataset).CalcCorrelationMatrix    1.02GB 45.93%   100%     1.02GB 45.93%  bytes.makeSlice         0     0%   100%     1.02GB 45.93%  bytes.(*Buffer).WriteByte         0     0%   100%     1.02GB 45.93%  bytes.(*Buffer).grow         0     0%   100%     1.02GB 45.93%  encoding/json.Indent所以我想知道我如何才能找出程序分配 17 GB 的原因,而峰值内存使用量似乎只有 ~2.5GB?有没有办法使用 pprof 跟踪整个程序的内存使用情况?编辑我再次使用 GODEBUG=gctrace=1 运行程序并得到以下跟踪:gc 1 @0.017s 0%: 0.005+0.55+0.003 ms clock, 0.022+0/0.47/0.11+0.012 ms cpu, 1227->1227->1226 MB, 1228 MB goal, 4 Pgc 2 @14.849s 0%: 0.003+1.7+0.004 ms clock, 0.015+0/1.6/0.11+0.018 ms cpu, 1227->1227->1227 MB, 2452 MB goal, 4 Pgc 3 @16.850s 0%: 0.006+60+0.003 ms clock, 0.027+0/0.46/59+0.015 ms cpu, 1876->1876->1712 MB, 2455 MB goal, 4 Pgc 4 @22.861s 0%: 0.005+238+0.003 ms clock, 0.021+0/0.46/237+0.015 ms cpu, 3657->3657->3171 MB, 3658 MB goal, 4 Pgc 5 @30.716s 0%: 0.005+476+0.004 ms clock, 0.022+0/0.44/476+0.017 ms cpu, 5764->5764->5116 MB, 6342 MB goal, 4 Pgc 6 @46.023s 0%: 0.005+949+0.004 ms clock, 0.020+0/0.47/949+0.017 ms cpu, 10302->10302->9005 MB, 10303 MB goal, 4 Pgc 7 @64.878s 0%: 0.006+382+0.004 ms clock, 0.024+0/0.46/382+0.019 ms cpu, 16548->16548->7728 MB, 18011 MB goal, 4 Pgc 8 @89.774s 0%: 0.86+2805+0.006 ms clock, 3.4+0/24/2784+0.025 ms cpu, 20208->20208->17088 MB, 20209 MB goal, 4 P所以很明显堆在整个程序中稳步增长,但我无法确定在哪里。pprof.WriteHeapProfile我在调用内存密集型函数后分析了内存使用情况:
查看完整描述

2 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

go profile 是一个采样分析器,并以特定的时间间隔对内存使用情况进行采样。在我的例子中,采样不够频繁,无法捕获使用大量内存的函数(JSON 编组)。

通过设置环境变量增加探查器的采样率

$ export GODEBUG=memprofilerate=1

将更新runtime.MemProfileRate并且配置文件现在包括每个分配的块。


查看完整回答
反对 回复 2023-06-19
?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

一个可能的解决方案(就像我的情况一样)是二进制文件是用 编译的-race,这样可以检查竞争条件。

这样做的开销是巨大的,如果用 或类似的东西检查的话,看起来像是一个巨大的内存泄漏htop,但不会显示在任何 pprof 输出中


查看完整回答
反对 回复 2023-06-19
  • 2 回答
  • 0 关注
  • 160 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信