2

我们认为我们的 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文档非常节俭。我们甚至难以理解它应该如何使用。我们的二进制文件是一个守护进程。例如:

  1. 如果我们从 开始阅读go tool pprof http://localhost:6060/debug/pprof/heap,这是在这个特定时间一次性阅读还是随着时间的推移汇总?
  2. 有时text稍后再次点击interactive mode似乎会报告相同的值。我们真的在看相同的价值观吗?我们是否需要重新启动go tool pprof...以获得新的值?
  3. 它是读取整个堆,还是读取堆栈中特定点的某个特定 go 例程....???

最后,这种解释是否正确(来自http://localhost:6060/debug/pprof/):

/debug/pprof/

profiles:
0   block
64  goroutine
45  heap
0   mutex
13  threadcreate

二进制有 64 个开放的 go 例程和总共 45MB 的堆内存?

4

0 回答 0