单个erlang进程占用更多内存并且触发进程内存高警报

时间:2016-03-31 10:17:03

标签: memory-management erlang gen-server

我有一个erlang gen_server,它以异步方式从客户端接收消息(使用强制转换)。在每个消息处理中,服务器将它们插入到有序的ETS表中并根据条件删除其中的一些(由于条件删除,ETS表中的记录数量大部分时间在5000左右。但是很少见可以将此大小增加到200k的场景,为插入和删除引入了开销。)

这种工作正常,直到每秒的消息数为100k但超过此值时,它会给我进程内存高水印并开始消耗大量内存。当我将插入和删除部分注释到有序的ets时,它可以每秒处理超过100k。你能给我一些关于如何解决这个问题的提示吗?

进程可以分配的内存最大限制是多少?我正在使用35 GB的内存,我将水印阈值设置为memsup:set_procmem_high_watermark(0.6) 。我也试过gbtree和有序字典,但是他们没有解决内存错误。

2 个答案:

答案 0 :(得分:1)

我有个建议。当它超过100k / s时,gen_server无法及时处理消息队列,因此它开始增长=> gen_server变慢并且内存泄漏。如果它增长,请尝试监控erlang:process_info(Pid, message_queue_len)

答案 1 :(得分:0)

处理内存限制

Erlang中没有这样的选项。 memsup:set_procmem_high_watermark/1只是设置进程内存分配的阈值。如果超过阈值,则会发出警报。

问题可能是什么原因?

一开始你必须找出你的流程为什么会变慢的原因。如前所述,检查消息队列的特征:它是否随着时间的推移而增长?如果是这种情况,您的流程将无法按照到达的速率处理邮件。 erlang:process_info/2会有所帮助。

要记住的另一件事是当您在ETS中插入/查找数据时,会复制对象。因此,如果删除对象时必须满足的条件涉及从ETS检索数据,那么也可能导致您的问题。

如何解决这个问题?

有几种方法可以解决这个问题。显而易见的一个是简单地使用背压机制,例如,让客户端同步发送消息。

你可以尝试将你的一个进程分成几个进程。为实现这一目标,您可以根据消息中包含的某些信息,让一个进程将消息分发给其他人。

最后,您可以尝试对您的ETS应用一些优化。例如,如果您要存储大型对象,则可以检查是否没有不必要地检索它们(使用ets:lookup/X代替ets:match/Xets:match_object/X来获取您的位数希望从存储的消息)。