go oom堆内存分析
go tool pprof http://localhost:6060/debug/pprof/heap
执行top命令
分析
从 go tool pprof
的输出结果来看,我们可以分析内存占用的热点和可能的内存问题。以下是分析结果:
输出解读
- flat:表示当前函数直接分配的内存大小(不包括它调用的其他函数的内存)。
- flat%:
flat
占总内存分配的百分比。 - cum:当前函数及其调用链的总内存分配。
- cum%:
cum
占总内存分配的百分比。
前 10 个内存热点如下:
函数名 | 直接内存 (flat) | 总内存 (cum) | flat% | cum% |
---|---|---|---|---|
runtime.malg | 146.56 MB | 146.56 MB | 56.93% | 56.93% |
fmt.init.func1 | 66.01 MB | 66.01 MB | 25.64% | 25.64% |
internal/poll.runtime_Semacquire | 24.50 MB | 24.50 MB | 9.52% | 9.52% |
golang.org/x/net/webdav.(*memFile).Write | 7.89 MB | 7.89 MB | 3.06% | 3.06% |
time.Sleep | 4 MB | 4 MB | 1.55% | 1.55% |
runtime.allgadd | 2.84 MB | 2.84 MB | 1.10% | 1.10% |
gindemo/pkg/controller/student.Oom.func1 | 1.50 MB | 97.02 MB | 0.58% | 37.69% |
fmt.Fprintln | 0 MB | 91.52 MB | 0% | 35.55% |
fmt.Println (inline) | 0 MB | 91.52 MB | 0% | 35.55% |
fmt.newPrinter | 0 MB | 66.01 MB | 0% | 25.64% |
问题分析
-
runtime.malg
runtime.malg
是 Go runtime 为 Goroutine 分配栈内存的函数。- 占用了 146.56MB (56.93%) 的内存,这说明程序可能创建了大量 Goroutine,每个 Goroutine 默认分配 2KB 的栈空间。
- 问题可能原因:
- Goroutine 使用不当,比如进入死循环或 Goroutine 泄漏。
- 某些操作频繁创建 Goroutine,而没有释放。
-
fmt.init.func1
fmt.init.func1
占用了 66.01MB (25.64%) 的内存,这通常和fmt
包的初始化有关。- 问题可能原因:
- 程序中过度使用
fmt.Println
、fmt.Sprintf
等方法,导致分配了大量字符串。 - 注意调用链中有
fmt.Println
和fmt.Fprintln
,两者累积占用了 91.52MB (35.55%) 的内存。
- 程序中过度使用
-
internal/poll.runtime_Semacquire
- 占用了 24.50MB (9.52%) 的内存,这通常和系统 I/O 操作或锁竞争有关。
- 问题可能原因:
- 某些操作在等待资源(如文件、网络连接或锁),未能释放。
- 检查程序是否有阻塞的 I/O 或锁使用问题。
-
golang.org/x/net/webdav.(*memFile).Write
- 占用了 7.89MB (3.06%) 的内存,这说明 WebDAV 的
Write
操作分配了一些临时内存。 - 问题可能原因:
- 如果
Write
被频繁调用,可能导致内存分配累积。 - 检查 WebDAV 文件操作是否可以优化。
- 如果
- 占用了 7.89MB (3.06%) 的内存,这说明 WebDAV 的
-
gindemo/pkg/controller/student.Oom.func1
- 该函数总共占用了 97.02MB (37.69%) 的内存(cum%)。
- 问题可能原因:
- 函数中可能存在大量内存分配,或频繁调用其他内存热点函数(如
fmt.Println
)。 - 需要进一步定位
student.Oom.func1
的具体实现逻辑。
- 函数中可能存在大量内存分配,或频繁调用其他内存热点函数(如