Node.js内存不足

29

今天我遇到了一个奇怪的问题。这对于其他人来说可能是一个简单的答案,但是它却让我困惑了。为什么下面的代码会导致内存错误?

var cur = 167772160;
var bcast = 184549375;
var addresses = [];
while (cur <= bcast){
  cur += 1;
  addresses.push(cur);
}
addresses.length 
addresses // memory goes from a few megs to over a gig in seconds when trying to print this

我得到了这两个错误之一......第一个是当我在Node的解释器中运行此代码时,而后一个是当我通过nodeunit运行它时:

致命错误:CALL_AND_RETRY_2分配失败 - 进程内存不足

致命错误:JS分配失败 - 进程内存不足


对于那些感兴趣的人,我转而使用缓冲区。 成功有限。https://dev59.com/tlvUa4cB1Zd3GeqPqin2 - Sneaky Wombat
3个回答

25

你可以通过传递 --max-old-space-size=<value> 来增加默认限制,它是以 MB 为单位的。

以下示例将允许 Node 使用最高达 4GB(4096 兆字节)的内存空间:

node --max-old-space-size=4096 app

5
4 GB实际上是4096,我尝试编辑你的回答,但更改的字符数少于6个。 - Ido

7
当我尝试访问数组时发生这种情况。 但获取长度不会出现此问题。
> var cur = 167772160;
> var bcast = 184549375;
> var addresses = [];
> while (cur <= bcast){
...   cur += 1;
...   addresses.push(cur);
... }
16777216
> addresses.length 
16777216
> addresses
FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory

这里有另一个与内存使用问题相关的SO问题:Node.js(和Chrome V8)中的内存限制


1
好的,那我不是唯一一个遇到这个问题的人。嗯,也许我应该把它放到Node.js的GitHub问题列表中去。 - Sneaky Wombat
是的,我之前看到了那个 Stack Overflow 的问题,但我认为这不仅仅是 Node 的问题了。我运行那段代码也可以让 Google Chrome 崩溃。唉。 - Sneaky Wombat
啊,谷歌浏览器也使用了 node.js 使用的相同的 v8 引擎。让我尝试看看不同的实现,因为存储 16,777,216 个九位数整数确实需要很多内存。 - ace

4

当我运行你的脚本时,我没有收到内存分配错误。你的系统有多少RAM?

编辑 根据作者的更新说明,我可以复制它。

Node试图将整个数组转换为字符串。该数组长度为16777216个元素。每个元素至少包含9位数。将其转换为一个150,994,994字符长的字符串。这只是一个巨大的操作,超出了node的内存能力。


4 GB,MacBook Air。一定要访问address.length属性。这就是我的程序崩溃的地方。我会添加它的。我忘了提到那部分。哈哈 - Sneaky Wombat
我的设置也可以正常工作。应该是 addresses.length 吗? - ace
是的,打错了。我刚刚看了一下活动监视器。如果你只是输入“addresses”并让它尝试打印数组,节点的内存使用量会在几秒钟内从几乎为零增加到超过1GB,然后崩溃。:( 令人悲伤 - Sneaky Wombat
1
我开始认为是toString或valueOf方法导致了这个崩溃。我在v8列表上发布了一个问题,值得一看。http://code.google.com/p/v8/issues/detail?id=1671 如果只有node支持yield关键字,我就不会写这样的代码了。我将尝试创建一个递归函数,并使用回调来模拟生成器的功能。这将消除创建包含所有这些值的数组的需要,因为我可以在程序的另一部分逐个处理它们。 - Sneaky Wombat
我同意创建一个函数来处理它比存储它们更好。 - ace
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接