Ale*_*exP 7 debugging erlang memory-leaks
我有一个具有以下模式的应用程序:
问题是"系统"部分不断增长(约1GB /周).
我的问题是如何调试存储在那里的内容或谁在该区域分配内存并且不释放它.
我已经测试过list:keysearch/3并且它似乎没有泄漏内存,因为这是我使用的唯一本机内容(没有端口,没有驱动程序,没有NIF,没有BIF,没有).Erlang版本是R15B03.
这是当前的erlang:memory()输出(轻微的流量,应用程序从2月03日开始):
[{total,378865650},
{processes,100727351},
{processes_used,100489511},
{system,278138299},
{atom,1123505},
{atom_used,1106100},
{binary,4493504},
{code,7960564},
{ets,489944},
{maximum,402598426}]
Run Code Online (Sandbox Code Playgroud)
这是一个64位系统.正如您所看到的,"系统"部分大约有270MB,"进程"大约为100MB(夜间降至约16MB).
看来我已经发现问题了。
我有一个“process_killer”gen_server,其中进程可以订阅定期 GC 或终止。它的订阅函数会在某些进程收到的每条消息上调用,以推迟 GC/kill(类似于重新准备)。
如果尚未监视,此进程将执行 erlang:monitor 以捕获死进程并将其从监视列表中删除。如果我在每条处理的消息上评论我们的重新订阅行,“系统”区域似乎表现正常。这意味着这是我的 process_killer 中的一个错误,它确实泄漏了监视器引用(请记住,您可以多次调用 erlang:monitor 并且每次调用都会创建一个引用)。
我之所以产生这个想法,是因为我测试了一个简单的模块,该模块在循环中调用 erlang:monitor,并且我看到每次调用都会增加约 13 字节的“系统”区域。
工人们自己也没什么问题,因为无论如何他们都会死,带着他们的显示器。有一个长时间运行的进程(从应用程序开始,从应用程序停止)将所有消息分派给对每条收到的消息调用 GC 重新启动的工作线程,因此我们正在讨论每个进程生成数以万计的监视器。小时并且从未发布。
我在这里写下这个答案以供将来参考。
TL;博士; 确保您不会在长时间运行的进程中泄漏监视器引用。