Erlang垃圾收集

我需要你的帮助来调查Erlang内存消耗的问题。 多么典型,不是吗?

我们有两种不同的部署scheme。

  • 在第一个scheme中,我们在小型虚拟机(在Amazon AWS中)上运行许多相同的节点,每台机器一个节点。 每台机器都有4Gb的RAM。
  • 在另一个部署scheme中,我们在大的裸机上运行这个节点(64G RAM),每台机器上有许多节点。 在此部署中,节点在Docker容器中隔离(内存限制设置为4 Gb)。

我注意到,docker化节点中的进程堆比内存负载相同的非docker化节点堆多了3倍多。 我怀疑非dockerized节点中的垃圾收集更积极。 不幸的是,我没有任何垃圾收集的统计数据,但我想尽快获得。

为了提供更多信息,我应该说我们在Ubuntu 14.04上使用HiPE R17.1和stock kernel。 在这两种scheme中,我们为每个节点运行8个调度程序,并使用默认的fullsweep_after标志。

我的盲目的build议是,Erlang的默认垃圾收集依赖(以某种方式) /proc/meminfo (这是不是在dockerized环境中实际)。 我不是C人,也不熟悉模拟器的内部,所以有人可能指向我负责垃圾回收的Erlang源代码以及一些我可以用来调整这种行为的模拟器选项?

不幸的是,虚拟机经常试图在内存pipe理方面比所需要的更聪明,并不总是与Erlang内存pipe理模型很好地搭配。 Erlang倾向于分配和释放大量的小块内存,这与正常的应用程序非常不同,后者通常会分配和释放less量的大块内存。

其中一种技术是透明超大页面 (THP),一些操作系统默认启用,导致运行在这些虚拟机上的Erlang节点增长(直到它们崩溃)。

https://access.redhat.com/solutions/46111

https://www.digitalocean.com/company/blog/transparent-huge-pages-and-alternative-memory-allocators/

https://docs.mongodb.org/manual/tutorial/transparent-huge-pages/

所以,确保THPclosures是您可以检查的第一件事。

另一个是试图调整启动Erlang虚拟机时使用的内存选项,例如看到这个post:

Erlang:内存使用情况的差异

为我们工作的结果选项:

 -MBas aobf -MBlmbcs 512 -MEas aobf -MElmbcs 512 

有关内存分配器的更多理论:

http://www.erlang-factory.com/static/upload/media/139454517145429lukaslarsson.pdf

内存分配器标志的更详细的描述:

http://erlang.org/doc/man/erts_alloc.html

首先要知道的是,我在Erlang的垃圾回收是基于进程的。 每个过程都是在自己的时间GC,并相互独立。 因此,系统中的垃圾回收只取决于进程中的数据,而不取决于操作系统本身。

也就是说,从Eralang的观点和系统观点来看,内存消耗可能会有一些差异。 为什么比较erlang:memory与你的系统所说的话总是一个好主意(它可能会显示一些二进制泄漏或其他内存问题)。

如果您想了解更多关于Erlang内部的知识,我会推荐这两个会谈:

https://www.youtube.com/watch?v=QbzH0L_0pxI

https://www.youtube.com/watch?v=YuPaX11vZyI

从更好的内存pipe理debugging,我可以推荐从http://ferd.github.io/recon/