繁体   English   中英

去:记忆问题

[英]Go: memory issues

我需要你的智慧。

我有一个用Go写的巨大守护进程。 前段时间,用户报告代码中某处可能存在内存泄漏。

我开始调查这个问题。 当主要代码检查没有让我得到关于泄漏性质的任何线索时,我试着关注我的过程如何工作。

我的想法很简单:如果我没有删除对某些对象的引用,我的堆应该不断增长。 我编写了以下过程来监视堆:

func PrintHeap() {
    ticker := time.NewTicker(time.Second * 5)
    for {
        <-ticker.C
        st := &runtime.MemStats{}
        runtime.ReadMemStats(st)
        // From Golang docs: HeapObjects increases as objects are allocated
        // and decreases as the heap is swept and unreachable objects are
        // freed.
        fmt.Println("Heap allocs:", st.Mallocs, "Heap frees:",
            st.Frees, "Heap objects:", st.HeapObjects)
    }
}

此过程每5秒打印一些有关堆的信息,包括当前分配的对象数。

现在谈谈守护进程的作用。 它处理来自某些UDP输入的行。 每行都包含有关某个HTTP请求的一些信息,并被解析为典型的Go结构。 此结构具有一些数字和字符串字段,包括一个用于请求路径。 然后这个结构发生了很多事情,但这些事情在这里是无关紧要的。

现在,我将输入速率设置为每秒1500行,每行相当短(您可以将其读作:使用标准请求路径, / )。

运行应用程序后,我可以看到堆大小在某个时间点稳定:

Heap allocs: 180301314 Heap frees: 175991675 Heap objects: 4309639
Heap allocs: 180417372 Heap frees: 176071946 Heap objects: 4345426
Heap allocs: 180526254 Heap frees: 176216276 Heap objects: 4309978
Heap allocs: 182406470 Heap frees: 177496675 Heap objects: 4909795
Heap allocs: 183190214 Heap frees: 178248365 Heap objects: 4941849
Heap allocs: 183302680 Heap frees: 178958823 Heap objects: 4343857
Heap allocs: 183412388 Heap frees: 179101276 Heap objects: 4311112
Heap allocs: 183528654 Heap frees: 179181897 Heap objects: 4346757
Heap allocs: 183638282 Heap frees: 179327221 Heap objects: 4311061
Heap allocs: 185609758 Heap frees: 181330408 Heap objects: 4279350

达到此状态后,内存消耗将停止增长。

现在,我改变了我的输入,使得每行变得超过2k chars(具有巨大的/AAAAA...请求路径),这就是奇怪的事情开始发生的地方。

堆大小急剧增长,但在一段时间后仍然变得稳定:

Heap allocs: 18353000513 Heap frees: 18335783660 Heap objects: 17216853
Heap allocs: 18353108590 Heap frees: 18335797883 Heap objects: 17310707
Heap allocs: 18355134995 Heap frees: 18336081878 Heap objects: 19053117
Heap allocs: 18356826170 Heap frees: 18336182205 Heap objects: 20643965
Heap allocs: 18366029630 Heap frees: 18336925394 Heap objects: 29104236
Heap allocs: 18366122614 Heap frees: 18336937295 Heap objects: 29185319
Heap allocs: 18367840866 Heap frees: 18337205638 Heap objects: 30635228
Heap allocs: 18368909002 Heap frees: 18337309215 Heap objects: 31599787
Heap allocs: 18369628204 Heap frees: 18337362196 Heap objects: 32266008
Heap allocs: 18373482440 Heap frees: 18358282964 Heap objects: 15199476
Heap allocs: 18374488754 Heap frees: 18358330954 Heap objects: 16157800

但是内存消耗增长并且从未停止过。 我的问题是:关于发生了什么的任何想法?

我想到了很多巨大的物体导致的内存碎片,但实际上我并不知道该怎么想。

你可以试试go memory分析工具。

首先,您需要更改程序,以便提供内存配置文件。 有几种方法可以解决这个问题。

  1. 您可以使用package net/http/pprof如果可以发布该端点,请参阅https://golang.org/pkg/net/http/pprof/
  2. 您可以使用包runtime/pprof ,并使程序将内存配置文件转储到已知位置,以响应特定事件,如接收信号或其他内容。

之后,您可以使用go tool pprof分析内存配置go tool pprof <path/to/executable> <file>如果您选择将内存配置文件转储到文件或作为go tool pprof <path/to/executable> http://<host>:<port>/debug/pprof/heap ,您可以调用go tool pprof <path/to/executable> <file> go tool pprof <path/to/executable> http://<host>:<port>/debug/pprof/heap ,如果你使用net/http/pprof和使用top5获得前5名的功能,其中大部分分配你的记忆。 您可以使用list命令查看特定函数,以查看分配了多少内存的行。

从那开始,您应该能够推断出您正在观察的内存增加。

您还可以在https://blog.golang.org/profiling-go-programs上阅读相关内容,其中还介绍了如何分析您的CPU使用情况。 只需搜索单词memprofile即可跳转到相关部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM