让我把我的问题简单化如下。我是一个内置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 **”时,我观察到高内存增长:内存命令那就是使用大部分内存。
但是成功处理事件时情况并非如此。
答案 0 :(得分:9)
失去的记忆基本上只能在三个地方出现:
gen_server的状态
您的流程邮箱
请注意,在正常的handle_info
sa receive
子句中,总有一些方法可以排除不匹配的消息(对于gen_server Any ->
回调)。
如果邮箱只是临时填满它,可能是因为接收过程对于产生的邮件速率来说太慢了。这通常是异步通信的问题。如果它只是暂时性的爆发而不会破坏任何东西,那就可以了。
在这种情况下,您可以优化接收流程
或修复您的协议以使用更少的消息
如果您有多个接收某些消息的功能,请确保定期调用所有接收部件。不要忘记Any ->
条款。
请注意,当您在gen_servers回调中处理时,不会收到任何消息,因此如果您需要更多时间进行回调,那么异步消息可能会堆积(例如随机消息到达+固定处理时间)建立一个无限制的增长队列,有关详细信息,请参阅Queueing theory
在您的ETS表中
答案 1 :(得分:7)
手动触发GC,看看内存会发生什么。
[garbage_collect(Pid) || Pid <- processes()]
答案 2 :(得分:3)
最有可能的是,您正在离开正在引用二进制文件的进程。如果进程终止,则将清除与该进程相关的所有内存(包括仅属于该进程的任何二进制文件)。
如果你仍然有泄漏的二进制文件,这意味着你有一个长时间运行的进程(服务器,单例等),它保持对二进制文件的引用,无论是在进程状态还是非尾递归函数。确保在进程通信超时或死亡后清理状态。另外,请检查是否使用非尾递归调用将对二进制文件的引用保留在堆上。