Golang在OOM上运行GC

Golang在OOM上运行GC,go,garbage-collection,Go,Garbage Collection,golang是否在面临OOM时运行GC并重试分配? 我们面临一个问题,kubernetes吊舱(运行go代码)在处理大型文件时被杀死 go代码处理许多文件,逐行读取它们,并为其解析的每一行(通过在循环中创建解析的结构-局部变量来分配一些内存),如果匹配某些条件,则将其插入DB。 这是为多个客户端并发运行的。 对于许多拥有小文件的客户机来说,这很好。但是当它遇到客户机的大文件时,它会发出OOM 我们的系统运行了很长时间,没有发现任何内存泄漏。即使是pprof分析也表明没有内存泄漏。当面临内存压力时

golang是否在面临OOM时运行GC并重试分配?
我们面临一个问题,kubernetes吊舱(运行go代码)在处理大型文件时被杀死

go代码处理许多文件,逐行读取它们,并为其解析的每一行(通过在循环中创建解析的结构-局部变量来分配一些内存),如果匹配某些条件,则将其插入DB。 这是为多个客户端并发运行的。 对于许多拥有小文件的客户机来说,这很好。但是当它遇到客户机的大文件时,它会发出OOM


我们的系统运行了很长时间,没有发现任何内存泄漏。即使是pprof分析也表明没有内存泄漏。

当面临内存压力时,OOM杀手是内核的最后手段。“要么我现在牺牲一个进程,要么整个系统可能无法使用。”

因为这是最后的手段(例如,内核在调用OOM killer之前很久就会选择减少文件系统缓存的可用内存量),所以选择牺牲的进程在这方面没有发言权,也没有早期警告1

在您的情况下,您可能没有耗尽物理内存,而是达到了容器的用户定义内存限制。但是内核也使用相同的工具来强制执行这个限制

您必须提高内存限制以考虑最坏情况下的工作负载,或者提高程序的内存消耗以保持在其限制内

考虑到小文件工作正常,您没有适当地限制并发性是有道理的。如果一次为每一行生成一个goroutine,那么在内存使用方面,读取整个文件没有根本区别


  • 您可以将SIGKILL更改为SIGTERM,但这对您没有帮助。如果您将SIGTERM的含义从“退出”更改为“释放一些内存到操作系统,但继续运行”,您的ops团队将讨厌您。无论如何,围棋也没有办法做到这一点

  • GC不会释放内存,它只能重用内存。您无法从进程内判断内存何时不足,这取决于系统。如果你不能再分配任何东西,你无论如何也不能运行GC。不,OOM杀手只是杀死一个进程。事先没有“警告”。在Go中分配内存失败的情况下,也是“否”。并发是多个客户端,而不是一个文件的每一行。一个客户机通常有40-50个文件,每个文件在我们处理的每个窗口中大约有10k行。我们试图在每处理1000行之后显式添加runtime.GC(),我们看到大文件也可以很好地运行。似乎我们需要以某种方式调整GC设置?@Pratham:您可以使用
    GOGC
    环境变量来调整GC,但这只能在下一个稍大的文件加载到内存中时延迟不可避免的时间,或者加载速度稍快。您需要以其他方式限制内存消耗。