erlang - 为什么 Erlang/Elixir 观察者内存使用数字不相加?

标签 erlang elixir phoenix-framework

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

如下面的屏幕截图所示,观察者报告总共使用了 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

Only thing I can think of is that those 23 MB has not been garbage collected yet. Is my assumption valid? If so, its been 6 hours since this container started. And I have been monitoring the memory consumption from very beginning. Shouldn't this be garbage collected by now?

第二个问题:我可以对 Erlang VM/Elixir 配置进行调整来优化内存占用吗?

最佳答案

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

丢失的兆字节

以下引用直接摘自 recon_alloc:memory() 的文档函数,并可能让您了解正在发生的事情:

The memory reported by `allocated' should roughly match what the OS reports. If this amount is different by a large margin, it may be the sign that someone is allocating memory in C directly, outside of Erlang's own allocator -- a big warning sign. There are currently three sources of memory alloction that are not counted towards this value: The cached segments in the mseg allocator, any memory allocated as a super carrier, and small pieces of memory allocated during startup before the memory allocators are initialized. Also note that low memory usages can be the sign of fragmentation in memory, in which case exploring which specific allocator is at fault is recommended.

所以我认为额外的 23 MB 内存使用可能是由一些不需要的分配引起的,或者可能是由于碎片引起的。


调整(非常小心/!\)

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

erl +SOMEFLAG +SOMEOTHERFLAG

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

因此,如果这确实是解决问题的唯一方法,我的建议是采用这些修改。在这种情况下,有一个 book关于 Erlang 运行时系统的信息帮助我理解了一些方面,所以我也建议提前阅读它。

注意:这里在黑暗中进行了疯狂的拍摄,并没有直接回答您的问题,但仔细检查您的二进制文件的情况可能会很有用,因为我看到报告了 13 MB由观察者。根据它们的大小(小于或大于 64 字节),它们存储在进程堆中或通过引用访问。我遇到过案例#1,大量小型二进制文件堆积起来,最终导致我的系统崩溃。


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

  • 此特定片段来自 blog post弗雷德·赫伯特 (Fred Hebert) 也是作者:

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

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

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

希望这有帮助:)

关于erlang - 为什么 Erlang/Elixir 观察者内存使用数字不相加?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50552773/

相关文章:

erlang - 如何根据内存使用情况分析 Erlang 程序?

erlang - 标签和版本升级的正确顺序

Docker没有执行bash文件的权限

elixir - 在 Elixir 中设置现有结构值?

elixir - 使用 Elixir 和 Phoenix 框架形成对象

sockets - 我无法获得通过在不老长寿药, Phoenix 中的存在而加入 channel 的所有用户的列表

erlang - 从头开始实现 pmap。为什么我的执行速度很慢?

Erlang 中的 Unicode 日志记录器

elixir - 在 Elixir 中打开模块?

Elixir/Plug/Phoenix : Calling halt doesn't stop downstream plugs from getting invoked during test