为什么Erlang / Elixir观察者的内存使用数量不加起来?

时间:2018-05-27 13:46:48

标签: erlang elixir phoenix-framework

当我使用iex连接到我的远程生产节点时,我开始使用Elixir并观察一些奇怪的行为。

如下面的屏幕截图所示,观察者报告正在使用总计 92 MB 内存。但是,当你总结进程,原子,二进制文件,代码和ets的内存消耗时,它会出现: ~69 MB

Processes  19.00 MB
    Atoms   0.97 MB (969 kB)
 Binaries  13.00 MB
     Code  28.00 MB
      ETS   7.69 MB (7685 kB)
-------------------
    Total  68.66 MB

enter image description here

所以,我的第一个问题是这个额外的 23 MB 内存来自哪里?我很确定这不仅仅是一个报道问题。因为当我查看我的Kubernetes pod的内存消耗时,它是 ~102 MB ,这与观察者显示的数字一致。

enter image description here

  

我唯一能想到的是那些 23 MB 尚未被垃圾收集。我的假设有效吗?如果是这样,自该容器启动以来已经过了6个小时。我一直在监视内存消耗。难道现在这不是垃圾收集吗?

第二个问题:我是否有任何可以优化内存占用的Erlang VM / Elixir配置调整?

1 个答案:

答案 0 :(得分:3)

我也一直在尝试解决有关OTP应用程序中的内存管理的问题,其中一个对我特别有用的工具是Fred Hebert编写的名为recon的库。尤其是recon_alloc模块,它提供了有关Erlang VM中内存使用情况的非常有用的信息。

丢失的兆字节

以下引文直接摘自recon_alloc:memory()函数的文档,可能使您对正在发生的事情有深刻的了解:

  

由“已分配”报告的内存应与操作系统大致匹配   报告。如果该金额相差很大,则可能是   表示有人在C之外直接在C中分配内存   Erlang自己的分配器-一个很大的警告信号。目前有   不计入此的三个内存分配源   值:mseg分配器中的缓存段,已分配的任何内存   作为超级载体,并在   在初始化内存分配器之前启动。另请注意   内存使用率低可能是内存碎片的迹象,其中   建议找出一个具体的分配器有问题的案例。

因此,我认为额外的23 MB内存使用量可能是由于某些不必要的分配所致,或者可能是由于碎片所致。


调整(非常小心/!\)

关于第二个问题,Erlang中有一个名为erts_alloc的工具,该工具还描述了内存分配器的手动配置。可以通过将命令行标志传递给仿真器来完成,例如:

erl +SOMEFLAG +SOMEOTHERFLAG

但是文档中有一个大的红色警告,强烈表明与默认配置相比,弄乱这些标志可能导致更糟糕的行为。

因此,我的建议是,如果确实是解决问题的唯一方法,请采用这些修改。在这种情况下,关于Erlang运行时系统的问题book可以帮助我理解某些方面,因此我还建议您事先对其进行阅读。

注意:此处在黑暗中狂野射击,无法直接回答您的问题,但仔细检查二进制文件的状态可能很有用,因为我发现已报告了13 MB由观察者。根据它们的大小(小于或大于64字节),它们被存储在进程堆中或通过引用进行访问。我遇到了第一种情况,其中堆满了许多小二进制文件,最终导致系统崩溃。


在尝试解决这些问题时,我发现了一些其他有用的资源:

  • Fred Hebert撰写的blog post中的这一特定代码段:
  

[erlang:garbage_collect(Pid) || Pid <- processes()].

它将立即在所有正在运行的进程上触发GC。就我而言,它创造了奇迹。您也可以添加一个选项以异步方式调用它,这样就不必在所有操作完成后进行阻塞:

  

[erlang:garbage_collect(Pid, [{async, RequestId}]) || Pid <- processes()].

希望这会有所帮助:)