我们认为我们的 Go 应用程序存在内存泄漏。
为了找出发生了什么,我们正在尝试使用pprof
.
我们很难理解读数。连接到 时go tool pprof http://localhost:6060/debug/pprof/heap?debug=1
,样本输出为
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) text
Showing nodes accounting for 17608.45kB, 100% of 17608.45kB total
Showing top 10 nodes out of 67
flat flat% sum% cum cum%
12292.12kB 69.81% 69.81% 12292.12kB 69.81% github.com/acct/repo/vendor/github.com/.../funcA /../github.com/acct/repo/vendor/github.com/../fileA.go
1543.14kB 8.76% 78.57% 1543.14kB 8.76% github.com/acct/repo/../funcB /../github.com/acct/repo/fileB.go
1064.52kB 6.05% 84.62% 1064.52kB 6.05% github.com/acct/repo/vendor/github.com/../funcC /../github.com/acct/repo/vendor/github.com/fileC.go
858.34kB 4.87% 89.49% 858.34kB 4.87% github.com/acct/repo/vendor/golang.org/x/tools/imports.init /../github.com/acct/repo/vendor/golang.org/x/tools/imports/zstdlib.go
809.97kB 4.60% 94.09% 809.97kB 4.60% bytes.makeSlice /usr/lib/go/src/bytes/buffer.go
528.17kB 3.00% 97.09% 528.17kB 3.00% regexp.(*bitState).reset /usr/lib/go/src/regexp/backtrack.go
(请原谅笨拙的混淆)
我们解释funcA
为消耗了近 70% 的内存——但这大约是 12MB。
现在top
虽然显示:
top - 18:09:44 up 2:02, 1 user, load average: 0,75, 0,56, 0,38
Tasks: 166 total, 1 running, 165 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3,7 us, 1,6 sy, 0,0 ni, 94,3 id, 0,0 wa, 0,0 hi, 0,3 si, 0,0 st
KiB Mem : 16318684 total, 14116728 free, 1004804 used, 1197152 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 14451260 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4902 me 20 0 1,371g 0,096g 0,016g S 12,9 0,6 1:58.14 mybin
这表明使用了 1.371 GB 的内存....它去哪儿了???
此外,pprof
文档非常节俭。我们甚至难以理解它应该如何使用。我们的二进制文件是一个守护进程。例如:
- 如果我们从 开始阅读
go tool pprof http://localhost:6060/debug/pprof/heap
,这是在这个特定时间一次性阅读还是随着时间的推移汇总? - 有时
text
稍后再次点击interactive mode
似乎会报告相同的值。我们真的在看相同的价值观吗?我们是否需要重新启动go tool pprof...
以获得新的值? - 它是读取整个堆,还是读取堆栈中特定点的某个特定 go 例程....???
最后,这种解释是否正确(来自http://localhost:6060/debug/pprof/):
/debug/pprof/
profiles:
0 block
64 goroutine
45 heap
0 mutex
13 threadcreate
二进制有 64 个开放的 go 例程和总共 45MB 的堆内存?