我一直在运行一个密码密集型应用程序,它正在生成伪随机字符串,具有特殊的结构和数学要求。在过去的8天里,它每个节点产生了大约170万个凭证号。生成过程是CPU密集型的,内存要求非常低。
在OTP-14B02上运行的Mnesia是存储数据库,并且在每个虚拟机内完成生成。我在集群中有3个节点,所有mnesia表disc_only_copies
类型。突然间,随着Solaris盒子上的活动增加(其他用户远程登录并启动了web服务器,ftp会话和其他任务),我的bash shell开始报告一个fork: not enough space
错误。
我的erlang Vms也发生了以下错误:
Crash dump was written to: erl_crash.dump temp_alloc: Cannot reallocate 8388608 bytes of memory (of type "root_set").
通常,我们会得到内存分配错误而不是memory re-location errors
,通常类型为"heap"
的内存是问题。这次,报告的内存类型是"root-set"
类型。
Qn 1.这个"root-set"
记忆是什么?
Qn 2.是否与CPU密集型活动有关? (为什么我要问这是当我开始任务时,机器响应说鼠标或键盘中断太慢意味着CPU太忙或其他一些我现在无法解释的问题)
Qn 3.可以避免这样的错误吗?如何 ?
答案 0 :(得分:1)
fork: not enough space
消息表明这是操作系统设置的问题,但是:
根集是垃圾收集器在搜索堆中 live 的数据时用作起点的内容。它通常从VM的寄存器开始,然后从堆栈中关闭,如果堆栈引用了仍需要存活的堆数据。在Erlang中可能还有其他根源我不知道,但这些是你开始的基本内容。
这是一个正好是8兆字节空间的重新分配错误,这可能意味着两件事之一。要么堆中没有8兆字节的空闲,要么堆的碎片无法识别,所以虽然它有8兆字节,但没有连续的这样的空间。
问题与CPU本身无关。你的内存不足了。一个大的根集可能表明你有一些非常深的递归,你可以在那里保存大量的数据指针。您可以重写代码,使其在尾部调用并在操作时使用更少的内存。
你应该更担心键盘和鼠标的响应时间慢。这可能表明某些事情是不对的。在进程运行时,vmstat 1,sysstat,htop,dstat或类似程序是否显示奇怪的内容?由于内存受限制,你也在寻找内核或C libc是否在这里做了一些奇怪的事情。
我不知道如何在不了解应用程序正在做什么的情况下修复它。由于您有崩溃转储,您的第一直觉应该是采用崩溃转储查看器并查看转储。目标是使用大量内存或具有深层堆栈的内存来查找进程。从那以后,您可以设法限制进程正在使用的内存量。通过重写代码以便它可以更早地提供内存,通过调整进程的垃圾收集设置(参见erlang手册页中的spawn选项),或者向系统添加更多内存。