Memory leaks 在Erlang应用程序中观察到内存泄漏

Memory leaks 在Erlang应用程序中观察到内存泄漏,memory-leaks,erlang,binary,Memory Leaks,Erlang,Binary,让我把我的问题简单地说如下。我的是一个内置于erlang的网络路由器软件,但在一个特定的场景中,我观察到非常高的内存增长,如VM所示。 我有一个进程从套接字接收来自其他进程的二进制数据包。 此过程解析二进制数据包并将二进制数据包传递给gen_服务器(称为handle_cast) gen_服务器再次在ETS表中存储一些信息,并将数据包发送到对等服务器。 当对等服务器响应时,ETS的条目被删除,gen_服务器响应第一个进程 此外,如果第一个进程(将数据包发送到gen_服务器)在等待ge

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

我有一个进程从套接字接收来自其他进程的二进制数据包。 此过程解析二进制数据包并将二进制数据包传递给gen_服务器(称为handle_cast)

gen_服务器再次在ETS表中存储一些信息,并将数据包发送到对等服务器。 当对等服务器响应时,ETS的条目被删除,gen_服务器响应第一个进程

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

现在,我观察到大量事件超时(由于对等服务器不可用)时内存的高速增长,根据我的研究,erlang:memory命令给出的“**二进制**”和“**进程使用**”占用了大部分内存。 但当成功处理事件时,情况并非如此。


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


如果您仍然有泄漏的二进制文件,这意味着您有一些长时间运行的进程(服务器、单例等),这些进程将二进制文件的引用保持在其进程状态或通过非尾部递归函数。确保在进程通信超时或通信中断后清除状态。此外,请检查是否使用非尾部递归调用在堆上保留对二进制文件的引用。

内存损失基本上仅在三个位置:

  • gen_服务器的状态

    • 看看你所在的州,看看那里是否有一些大的或正在成长的东西
  • 您的进程和邮箱

    • 请注意,在正常的
      receive
      s a
      Any->
      子句中,有一些方法可以始终排出不匹配的消息(对于gen_server
      handle\u info
      callback)

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

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

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

      • 如果有多个函数接收某些消息,请确保所有接收部分都被定期调用。不要忘记
        Any->
        条款

    • 请注意,当您在gen_服务器回调中处理时,不会收到任何消息,因此,如果您在回调中需要更多的时间,则异步消息可能会堆积起来(例如,随机消息到达+固定处理时间会构建一个无限增长的队列,有关详细信息,请参阅

  • 在你的桌子上

    • 可能ETS中的信息没有完全删除?在某些情况下忘记删除某些内容

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

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

    [垃圾收集(Pid)| | Pid所以,当事件超时时,似乎您有一个错误。您有什么问题?在超时期间观察到内存增长,这是我的问题。不知道为什么二进制大小在增长,即使我没有在任何进程中存储二进制文件。我只是在收到事件后立即发送UDP。似乎引用计数的二进制文件正在被复制我不能被垃圾收集……但为什么只有在超时时才被垃圾收集?@Adam:谢谢。你很接近答案。是gen服务器显示了大量内存。你知道如何清理引用的二进制文件吗?@ArunMu:只要在将来的状态中停止引用它们,例如,将状态向量记录中的字段设置为未定义,甚至设置为新的二进制文件ry.作为更新,在我的gen_服务器邮箱中,我可以看到许多消息和二进制数据包。这些消息是“第一个进程”处理的消息正在发送到gen_服务器,询问ETS表ID。有什么想法吗?@Peer:我没有在状态中维护任何二进制数据。@ArunMu:如果您没有在状态中维护大量数据,那么您就不会有正常的内存泄漏:在gen_服务器中,只保留传递的状态。内存可能是堆积在邮箱中的邮件.这里的问题是为什么?两个可能的原因:溢出或不接收存储..但这是我一直在做的事情。我只是想知道为什么erlang不会自己触发它谢谢..这解释了很多,因为我正在使用handle_cast进行异步通信。但是由于内存没有释放,我正在手动进行垃圾收集当检测到高超时时。所有这些都非常好。此外,由于gen_服务器是按顺序处理所有消息的中心,您是否可以做些什么来进一步并行化活动?(在接收过程中处理更多,产生额外的处理过程等)