Erlang ETS内存碎片

Erlang ETS memory fragmentation

我有一个 erlang 集群,其中 erlang:memory() 'total' 从空闲到繁忙时间每天都在 2-2.5GB 之间。 ets 内存使用量大约为 440M,并且无论如何都会保持在那里。 ets 中的数据非常短暂,全天都在变化。保证明天的数据与今天的数据没有共性。

Linux top 说 beam 正在使用大约 10 GB 的空间。 free -m 'used' 同意这一点(机器实际上只运行光束)。系统的整体内存使用量有规律地增长,例如在 16GB 系统上每天增长 1%。节点之间存在一些差异,但差异不大,并且 OS 'used' 内存总是比 erlang:memory() 总内存多几倍。

erlang:system_info({allocator, ets_alloc}) 显示 20 个分配器。大多数数据看起来像这样(命令的完整输出是 here):

    {mbcs_pool,[{blocks,2054},
   {blocks_size,742672},
   {carriers,10},
   {carriers_size,17825792}]},

1) 这是否意味着 742K 字节(字?)的内存实际上占用了 17M 的 OS 内存? 2) 正如 this post 所建议的那样,我们是否应该将“+MEas bf”添加到 VM args,以减少开销? 3) 我还能做些什么来避免 运行 内存不足?

这是 R17.5,但我们将在下一次部署(本周)中迁移到 R19.3。我们在当前部署中没有侦察,但将在下一次部署中添加它。另外,无法想象这很重要,但是光束 运行 在高山容器中。

以防其他人 运行 稍后进入:这实际上并不是内存泄漏。

erlang 的默认内存分配器策略可能不是您使用的最佳选择,这取决于您的操作以及 erlang 分配块的配置方式。事实证明,在某些情况下,由于分配器碎片,从 erlang 的角度来看 "free" 内存不一定会立即释放到 OS。

这里稍微解释一下:http://erlang.org/doc/man/erts_alloc.html

我们当时使用的erlang版本的默认分配器策略是aoffcbf(address order first fit carrier best fit)。在我们的例子中,这导致了非常高的内存碎片(10+GB 开销值)。在解决这些问题时,erlang:system_info(allocator)erlang:system_info({allocator, Alloc}) 是您的朋友。更改为 aobff(最适合的地址顺序)可提高内存使用效率。事实上,只要机器没有 运行 超出物理内存,就没有关系,但对我们来说,我们正在危险地接近物理极限。而且您不想开始分页。使用 aobff,我们从未超过 4GB,即使在节点启动 18 个月后也是如此。使用 aoffcbf,我们将在几周内超过 10GB。

一如既往,YMMV,因为这完全取决于分配的块的类型、大小等,以及它们的寿命。