erlang 将数百万条记录写入mnesia表会占用大量内存(RAM),并且即使删除这些记录也无法回收

06odsfpq  于 2022-12-16  发布在  Erlang
关注(0)|答案(1)|浏览(162)

我正在运行一个Erlang应用程序,它经常向mnesia表中写入数百万条记录,以便生成调度程序。当时间到期时,记录将被执行并从表中删除。表是用{type, disk_copies}, {type, ordered_set}配置的。我使用事务操作来写入记录,使用脏操作来删除记录。
我做了一个实验,写了200万条记录,然后全部删除:RAM内存在完成后没有回收。当我开始删除那些记录时,有一个尖峰,内存增加了两倍。例如,beam内存开始为75MB,实验后变为410MB。我使用erlang:memory()检查了前后的内存,发现内存被process_used and binary吃掉了,但实际上,我没有对binary进行任何操作。如果我对所有正在运行的进程使用erlang:garbage_collect(Pid),内存将被回收,剩下180MB。
任何解决此问题的建议将不胜感激。非常感谢。

bybem2ql

bybem2ql1#

Elrang OTP的Rickard绿色回答:

上述情况并不表明存在缺陷。
除非进程达到某些限制,否则不会进行垃圾收集。例如,它需要分配堆数据,但没有可用的堆。如果进程停止执行,则无论经过多长时间,它都不会自动进行垃圾收集,除非它达到这些限制之一。不过,可以通过调用erlang:garbage_collect()强制进行垃圾收集。
拥有大量实时数据的流程(并且由此已经变大)但是在垃圾收集时没有活动数据不会立即缩减到其原始大小。相反,它将获得相对较大的堆。堆空间是空闲的,以供进程使用,但它是从系统的Angular 分配的。选择相对较大的堆是为了避免不必要地频繁触发垃圾收集。
在你执行的时候,不仅你的进程会受到影响,而且其他进程也会建立堆来为你的进程服务。
如果你通过top或类似的方式来观察内存消耗,那么即使你能够将每个进程垃圾回收到它的初始大小,内存使用量也会在执行后增加。这是由于内存分配器将内存块放置到更大的内存块中,直到整个内存块空闲时才能删除。或多或少存在的每一个内存分配系统都有这个特性。

相关问题