简体   繁体   English

去:记忆问题

[英]Go: memory issues

I need your wisdom. 我需要你的智慧。

I have a huge daemon written in Go. 我有一个用Go写的巨大守护进程。 Some time ago a user reported that there might be a memory leak somewhere in the code. 前段时间,用户报告代码中某处可能存在内存泄漏。

I started investigating the issue. 我开始调查这个问题。 When primary code inspection didn't lead me to any clues about the nature of this leakage, I tried to focus on how my process works. 当主要代码检查没有让我得到关于泄漏性质的任何线索时,我试着关注我的过程如何工作。

My idea was simple: if I failed to remove references to certain objects, my heap should be constantly growing. 我的想法很简单:如果我没有删除对某些对象的引用,我的堆应该不断增长。 I wrote the following procedure to monitor heap: 我编写了以下过程来监视堆:

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)
    }
}

This procedure prints some info about heap each 5 seconds, including the number of objects currently allocated. 此过程每5秒打印一些有关堆的信息,包括当前分配的对象数。

Now a few words about what the daemon does. 现在谈谈守护进程的作用。 It processes lines from some UDP input. 它处理来自某些UDP输入的行。 Each line bears some info about a certain HTTP request and is parsed into a typical Go struct. 每行都包含有关某个HTTP请求的一些信息,并被解析为典型的Go结构。 This struct has some numeric and string fields, including one for request path. 此结构具有一些数字和字符串字段,包括一个用于请求路径。 Then lots of things happens to this struct, but those things are irrelevant here. 然后这个结构发生了很多事情,但这些事情在这里是无关紧要的。

Now, I set the input rate to 1500 lines per second, each line being rather short (you may read this as: with standard request path, / ). 现在,我将输入速率设置为每秒1500行,每行相当短(您可以将其读作:使用标准请求路径, / )。

After running the application I could see that heap size stabilizes at some point of time: 运行应用程序后,我可以看到堆大小在某个时间点稳定:

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

When this state was reached, memory consumption stopped to grow. 达到此状态后,内存消耗将停止增长。

Now, I changed my input in such a way that each line became more than 2k chars long (with a huge /AAAAA... request path), and that's where weird things started to happen. 现在,我改变了我的输入,使得每行变得超过2k chars(具有巨大的/AAAAA...请求路径),这就是奇怪的事情开始发生的地方。

Heap size grew drastically, but still became sort of stable after some time: 堆大小急剧增长,但在一段时间后仍然变得稳定:

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

But memory consumption grew liearly and never stopped. 但是内存消耗增长并且从未停止过。 My question is: any ideas about what's going on? 我的问题是:关于发生了什么的任何想法?

I thought about memory fragmentation due to lots of huge objects, but actually I don't really know what to think. 我想到了很多巨大的物体导致的内存碎片,但实际上我并不知道该怎么想。

You could try the go memory profiling tools. 你可以试试go memory分析工具。

First you need to alter your program so it provides a memory profile. 首先,您需要更改程序,以便提供内存配置文件。 There are several ways to this. 有几种方法可以解决这个问题。

  1. You can use package net/http/pprof see https://golang.org/pkg/net/http/pprof/ if it is ok for you to publish that endpoint. 您可以使用package net/http/pprof如果可以发布该端点,请参阅https://golang.org/pkg/net/http/pprof/
  2. You can use package runtime/pprof and make your program dump a memory profile to a known location in response to specific events like receiving a signal or something. 您可以使用包runtime/pprof ,并使程序将内存配置文件转储到已知位置,以响应特定事件,如接收信号或其他内容。

After that you can analyse the memory profile using the go tool pprof which you can either invoke as go tool pprof <path/to/executable> <file> if you chose to dump a memory profile to a file or as go tool pprof <path/to/executable> http://<host>:<port>/debug/pprof/heap if you used net/http/pprof and use top5 to get the top 5 functions, which allocated most of your memory. 之后,您可以使用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名的功能,其中大部分分配你的记忆。 You can than use the list command for specific functions to see which lines allocated how much memory. 您可以使用list命令查看特定函数,以查看分配了多少内存的行。

Starting from that, you should be able to reason about the increase in memory you are observing. 从那开始,您应该能够推断出您正在观察的内存增加。

You can also read about this at https://blog.golang.org/profiling-go-programs which also describes how to profile your cpu usage. 您还可以在https://blog.golang.org/profiling-go-programs上阅读相关内容,其中还介绍了如何分析您的CPU使用情况。 Just search for the word memprofile to jump to the relevant parts. 只需搜索单词memprofile即可跳转到相关部分。

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

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