Erlang应用程序中观察到的内存泄漏

时间:2011-02-18 06:51:02

标签: memory-leaks erlang binary

让我把我的问题简单化如下。我是一个内置erlang的网络路由器软件,但在特定情况下,我观​​察到内存增长非常高,如VM所示。

我有一个进程从socket接收来自其他进程的二进制数据包。

此过程解析二进制数据包并将二进制数据包传递给gen_server(调用handle_cast)

gen_server再次将一些信息存储在ETS表中,并将数据包发送到对等服务器。

当对等服务器响应时,删除来自ETS的条目,并且gen_server响应回第一个进程

此外,如果第一个进程(发送数据包到gen_server)在等待gen_server响应的5秒后得到timedout,它也会删除gen_server中的ETS条目并退出。

现在,当大量事件超时(由于对等服务器不可用)以及我研究了erlang给出的“** binary **”和“** processes_used **”时,我观察到高内存增长:内存命令那就是使用大部分内存。

但是成功处理事件时情况并非如此。

3 个答案:

答案 0 :(得分:9)

失去的记忆基本上只能在三个地方出现:

  1. gen_server的状态

    • 看看你的状态,看看那里是否有一些大的或不断增长的东西
  2. 您的流程邮箱

    • 请注意,在正常的handle_info sa receive子句中,总有一些方法可以排除不匹配的消息(对于gen_server Any ->回调)。

    • 如果邮箱只是临时填满它,可能是因为接收过程对于产生的邮件速率来说太慢了。这通常是异步通信的问题。如果它只是暂时性的爆发而不会破坏任何东西,那就可以了。

      • 在这种情况下,您可以优化接收流程

      • 或修复您的协议以使用更少的消息

      • 如果您有多个接收某些消息的功能,请确保定期调用所有接收部件。不要忘记Any ->条款。

    • 请注意,当您在gen_servers回调中处理时,不会收到任何消息,因此如果您需要更多时间进行回调,那么异步消息可能会堆积(例如随机消息到达+固定处理时间)建立一个无限制的增长队列,有关详细信息,请参阅Queueing theory

  3. 在您的ETS表中

    • 也许ETS中的信息没有完全删除?在某些情况下忘了删除某些东西?

答案 1 :(得分:7)

手动触发GC,看看内存会发生什么。

[garbage_collect(Pid) || Pid <- processes()] 

答案 2 :(得分:3)

最有可能的是,您正在离开正在引用二进制文件的进程。如果进程终止,则将清除与该进程相关的所有内存(包括仅属于该进程的任何二进制文件)。

如果你仍然有泄漏的二进制文件,这意味着你有一个长时间运行的进程(服务器,单例等),它保持对二进制文件的引用,无论是在进程状态还是非尾递归函数。确保在进程通信超时或死亡后清理状态。另外,请检查是否使用非尾递归调用将对二进制文件的引用保留在堆上。