【问题标题】:Erlang garbage collectionErlang 垃圾回收
【发布时间】:2016-02-11 04:19:41
【问题描述】:

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

我们有两种不同的部署方案。

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

我注意到,与负载相同的非 dockerized 节点中的堆相比,dockerized 节点中的进程堆占用的 RAM 高达 3 倍。我怀疑非 dockerized 节点中的垃圾收集更具侵略性。 不幸的是,我没有任何垃圾收集统计信息,但我想尽快获得它。

为了提供更多信息,我应该说我们在带有股票内核的 Ubuntu 14.04 上使用 HiPE R17.1。在这两种方案中,我们每个节点运行 8 个调度程序,并使用默认的 fullsweep_after 标志。

我的盲目建议是,Erlang 默认垃圾收集(不知何故)依赖于/proc/meminfo(这在 dockerized 环境中并不实际)。 我不是 C-guy 也不熟悉模拟器内部结构,所以有人可以指出 Erlang 源代码中负责垃圾收集的地方以及我可以用来调整这种行为的一些模拟器选项吗?

【问题讨论】:

  • Erlang 社区在这个网站上非常稀少(不过,了解内部原理的人知道内部原理)。您可能还想把它放在邮件列表中;那里有很多人对内部结构了解很多。
  • 另外,请说明您是如何获得该内存消耗数据的。如果它来自诸如 top 或 /proc/meminfo 之类的 OS 实用程序,那么您看到的原因可能与您从 erlang:memory/0 获取内存数据的原因大不相同。
  • 我正在使用一些不同的方式直接在 erlang 节点上收集统计信息。特别是我用erlang:memory/0,看到erlang:memory(processes)异常。我也有一些特定主管下的进程堆统计数据(我通过erlang:process_info(Pid, total_heal_size)在主管下的每个进程上获得它。

标签: garbage-collection erlang docker


【解决方案1】:

不幸的是,VM 经常尝试在内存管理方面做得比必要的更智能,但这并不总是能很好地与 Erlang 内存管理模型配合使用。 Erlang倾向于分配和释放大量的小块内存,这与普通应用程序通常分配和释放少量的大块内存有很大不同。

其中一项技术是透明大页面 (THP),某些操作系统默认启用该技术,这会导致在此类 VM 中运行的 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/

因此,确保 THP 已关闭是您可以检查的第一件事。

另一个是尝试调整启动 Erlang VM 本身时使用的内存选项,例如看这篇文章:

Erlang: discrepancy of memory usage figures

对我们有用的结果选项:

-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

【讨论】:

  • 我不确定 THP 或 HugePages 如何与 Erlang VM 内存消耗模型交互。有什么想法吗?
  • 这是一个对 Erlang 邮件列表 erlang.org/community/mailinglists 的一个很好的问题
【解决方案2】:

首先要知道,Erlang 中的垃圾收集是基于进程的。每个进程都在自己的时间进行GC,并且相互独立。因此,系统中的垃圾收集仅依赖于进程中的数据,而不是操作系统本身。

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

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

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

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

从更好的内存管理调试我可以推荐从http://ferd.github.io/recon/ 开始

【讨论】:

  • 感谢您的链接!我已经尽可能地使用recon。我对erlang:memory/0 所说的内容和我在主机上看到的内容有很好的统计。我也搜索了 bin 泄漏,但二进制文件的使用并没有让我受苦。只有一件奇怪的事情 - 异常的 erlang 进程堆使用(见 erlang:memory(processes) 或 erlang:process_info(total_heap_size)。
  • 您不应该使用erlang:memory(processes_used) 来计算实际进程堆大小吗?
  • 啊,是的。我忘记了。 erlang:memory(processes) 代表分配的内存,erlang:memory(processes_used) 代表实际使用的内存,对吗?此外,我对每个 erlang 分配器(包括 eheap_alloc)都有单独的统计信息。所有这些指标(进程、processes_used 和 eheap_alloc)几乎相同(每 Gb 加减几兆字节)。
猜你喜欢
  • 2013-12-29
  • 2011-12-21
  • 2012-01-28
  • 2013-06-27
  • 2011-11-29
  • 2021-12-20
  • 2011-07-15
  • 2014-03-09
  • 2013-06-10
相关资源
最近更新 更多