7

我有一个具有以下模式的应用程序:

  • 2 个长时间运行的进程在一些空闲时间后进入休眠状态,并且它们的内存消耗按预期下降
  • N (0 < N < 100) 个工作进程,它们在空闲超过 10 秒时执行某些工作并休眠,如果空闲超过两个小时则终止
  • 在夜间,当没有活动时,进程内存会恢复到与应用程序启动时几乎相同的值,这是预期的,因为所有工作人员都已死亡。

问题是“系统”部分不断增长(大约 1GB/周)。

我的问题是如何调试存储在那里的内容或谁在该区域分配内存而不释放它。

我已经测试了 lists:keysearch/3并且它似乎没有泄漏内存,因为这是我正在使用的唯一本地东西(没有端口,没有驱动程序,没有 NIF,没有 BIF,什么都没有)。Erlang 版本是 R15B03。

这是当前的erlang:memory()输出(少量流量,应用程序于 2 月 3 日启动):

[{total,378865650},
{processes,100727351},
{processes_used,100489511},
{system,278138299},
{atom,1123505},
{atom_used,1106100},
{binary,4493504},
{code,7960564},
{ets,489944},
{maximum,402598426}]

这是一个 64 位系统。如您所见,“系统”部分有约 270MB,而“进程”约为 100MB(夜间下降至约 16MB)。

4

1 回答 1

4

看来我找到了问题所在。

我有一个“process_killer”gen_server,其中进程可以订阅定期 GC 或终止。它的订阅函数在某些进程收到的每条消息上被调用,以推迟 GC/kill(类似于重新武装)。

如果尚未监视此进程,则执行 erlang:monitor 以捕获死进程并将其从监视列表中删除。如果我在每条处理的消息上评论我们的重新订阅行,“系统”区域似乎表现正常。这意味着它是我的 process_killer 中的一个错误,它确实泄漏了监视器引用(请记住,您可以多次调用 erlang:monitor 并且每次调用都会创建一个引用)。

我之所以产生这个想法,是因为我测试了一个简单的模块,它在循环中调用 erlang:monitor,并且我看到每次调用都会增加约 13 字节的“系统”区域。

工人们自己都还好,因为无论如何他们都会带着他们的显示器死去。有一个长时间运行的(从应用程序开始,从应用程序停止)进程将所有消息发送给在收到的每条消息上调用 GC re-arm 的工作人员,所以我们谈论的是每个产生的数以万计的监视器小时,从未释放。

我在这里写下这个答案以供将来参考。

TL;博士; 确保您没有在长时间运行的过程中泄漏监视器参考。

于 2013-02-09T13:10:18.730 回答