Erlang Binary Leak?

时间:2017-09-13 14:35:00

标签: erlang elixir beam

我们有一个处理大型json有效负载的erlang / elixir应用程序(在18 / erts 7.3.1上)。

这是一个典型的工作流程:

  1. 侦听器从rabbitmq获取一个令牌并发送到gen_server。

  2. gen_server将令牌放入带有未来时间(当前+ n秒)的ETS表中。 gen_server中的计划作业将从ETS中获取过期的令牌,并使用这些令牌启动几个短期过程。

  3. 这些短暂的进程从elasticsearch(使用hackney)下载30-50k json有效负载并对其进行处理,然后将结果上传回elasticsearch,然后进程立即死亡。我们跟踪这些过程并确认它们已经死亡。我们每秒处理5-10个这样的请求。

  4. 问题:我们看到一个不断增长的二进制空间,并且在48小时内它增长到几个GB(通过观察者和调试打印看到)。手动GC也没有影响。

    我们已经添加了“recon”并运行了recon:bin_leak,但是这只会释放几KB并且不会对不断增长的二进制空间产生影响。

    堆栈:Erlang 18 / erts 7.3.1,elixir 1.3.4,hackney 1.4.4,毒药2.2.0,timex 3.1.13等,这些应用程序都没有内存。

    过去有没有人遇到过类似的问题?非常感谢任何解决方案。

    2009年9月15日更新:

    我们更新了我们的应用程序到Erlang 19 / ERTS 8.3和hackney和毒药库到最新,仍然没有进展。这是GenServer中的一些日志,它使用spawn / receive或send_after定期向自己发送消息。在每个handle_info中,它查找一个ets表,如果它找到任何“符合条件”的条目,它会产生新的进程。如果没有,它只返回一个{:noreply,state}。我们在函数入口处打印VMs二进制空间信息(以KB为单位),日志列在下面。这是一天中的“空闲时间”。你可以看到二进制空间的逐渐增加。再一次:recon.bin_leak(N)或:erlang.garbage_collect()对这种增长没有影响。

    11:40:19.896 [warn] binary 1:3544.1328125

    11:40:24.897 [warn] binary 1:3541.9609375

    11:40:29.901 [warn] binary 1:3541.9765625

    11:40:34.903 [warn] binary 1:3546.2109375

    ---一些处理---

    12:00:47.307 [warn] binary 1:7517.515625

    ---一些处理---

    12:20:38.033 [warn] binary 1:15002.1328125

    在我们的旧Scala / Akka应用程序中,我们从来没有遇到这样的情况,该应用程序多年来处理的运行量增加了30倍而没有出现问题或重新启动。我写了两个应用程序。

1 个答案:

答案 0 :(得分:1)

我们发现memory_leak来自一个私有的可重用库,该库向Graylog发送消息,并使用下面的函数压缩该数据,然后通过gen_udp发送它。

defp compress(data) do
    zip = :zlib.open()
    :zlib.deflateInit(zip)
    output = :zlib.deflate(zip, data, :finish)
    :zlib.deflateEnd(zip)
    :zlib.close(zip)  #<--- was missing, hence the slow memory leak.
    output
end

相反,使用term_to_binary(数据,[:压缩])我可以省去一些麻烦。

感谢所有的输入和评论。非常感谢!