2011-02-18 42 views
4

让我把我的问题简单如下。 Mine是在erlang中构建的网络路由器软件,但在特定情况下,我正在观察VM显示的非常高的内存增长。 在Erlang应用程序中观察到的内存泄漏

我有一个进程从套接字的某个其他进程接收二进制包。

这个过程中,解析二进制分组和经过二进制分组到gen_server(handle_cast称)

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

当对等服务器返回响应从所述ETS的条目被删除,gen_server返回响应所述第一过程

此外,如果第一进程(其发送的分组到gen_server)5秒后获取已逾时等待来自gen_server响应它也会删除gen_server中的ETS条目并退出。

现在我观察,当大量的事件被超时(由于对等服务器不可用)高内存增长,从我已经研究其对“** **的二进制”和“** processes_used **“由erlang给出:使用大部分内存的内存命令。

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

+0

因此,看起来你有一个错误,当事件超时。你有什么问题? – 2011-02-18 06:54:25

+0

在超时期间观察到的内存增长是我的问题。不知道为什么二进制大小增长,即使我没有在任何进程中存储二进制文件。我只是在UDP收到它们后立即发送事件。似乎引用计数的二进制文件被复制,不能被垃圾收集......但为什么只有超时? – Arunmu 2011-02-18 06:58:41

回答

7

失去基本可以存储只在三个地方:

  1. 您gen_server

    • 看看你的状态,找出是否有一些大的或增长的东西有
    • 的状态
  2. 你的过程邮箱

    • 看到它有一些方法来总是消耗不匹配的消息(对于gen_server handle_info回调)在正常的receive条款Any ->条款。

    • 如果邮箱只是暂时填满它,可能是因为接收过程对于生成的邮件的速率太慢。这通常是异步通信的问题。如果它唯一的暂时性爆发不会破坏任何这些可能是有意的。

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

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

      • 如果你有收到一些邮件多种功能,确保所有接收部分被定期打电话。不要忘记Any ->子句。

    • 要知道,当你在一个gen_servers处理回调没有消息会被接受,所以如果你需要更多的时间回调,这将是必要的asyncronous消息可能会堆积起来(例如,随机消息的到达+固定处理时间建立一个无界日益增长的队列,详见Queueing theory

  3. 在你ETS表

    • 也许信息在ETS中是不是完全删除?在某些情况下忘记删除某些内容?
3

很有可能您正在运行的引用了二进制文件的进程正在运行。如果某个进程死亡,则与该进程相关的所有内存都将被清除(包括仅属于该进程的任何二进制文件)。

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

+0

@Adam:谢谢。你很接近答案。它是显示大量内存的gen server。任何想法如何清理引用的二进制文件? – Arunmu 2011-02-18 10:56:37

+1

@ArunMu:在未来的状态下停止引用它们,例如通过将状态向量记录中的字段设置为未定义的或甚至是新的二进制文件。 – 2011-02-18 12:23:17

7

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

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