Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 无限循环中的NodeJS内存消耗_Javascript_Node.js_Memory Leaks_Infinite Loop_V8 - Fatal编程技术网

Javascript 无限循环中的NodeJS内存消耗

Javascript 无限循环中的NodeJS内存消耗,javascript,node.js,memory-leaks,infinite-loop,v8,Javascript,Node.js,Memory Leaks,Infinite Loop,V8,我不知道这是Node还是V8的bug,但是如果我运行以下代码,节点进程就会泄漏内存。GC似乎从未启动过,几秒钟后它就消耗了超过1GB的内存。这是意想不到的行为。我错过什么了吗 代码如下: for(;;) { console.log(1+1); } 显然,这是一个有点人为的情况,但我可以看到一个长期运行的进程永远不会释放内存的问题 编辑:我尝试了v0.5.10(不稳定)和v0.4.12(稳定),不稳定的版本性能稍好一些——稳定的版本只是停止输出到控制台,但继续消耗内存,而稳定的版本会继续执行并消

我不知道这是Node还是V8的bug,但是如果我运行以下代码,节点进程就会泄漏内存。GC似乎从未启动过,几秒钟后它就消耗了超过1GB的内存。这是意想不到的行为。我错过什么了吗

代码如下:

for(;;) { console.log(1+1); }
显然,这是一个有点人为的情况,但我可以看到一个长期运行的进程永远不会释放内存的问题


编辑:我尝试了v0.5.10(不稳定)和v0.4.12(稳定),不稳定的版本性能稍好一些——稳定的版本只是停止输出到控制台,但继续消耗内存,而稳定的版本会继续执行并消耗内存,不会暂停。

您永远不会返回node.js事件循环,这是在阻止它

当您将某些内容写入流节点时,js会异步执行此操作:它发送写入请求,在流的内部数据结构中对有关已发送请求的信息进行排队,并等待将通知其完成的回调

如果您阻止事件循环,则永远不会调用回调(因为传入的事件永远不会被处理),流中排队的辅助数据结构也永远不会被释放


如果您通过使用nextTick/setInterval/setTimeout不断地调度自己的事件来“重载”事件循环,也可能发生同样的情况。

@VyacheslavEgorov的答案似乎是正确的,但我想推迟到事件循环会解决问题。您可能需要比较无限循环
与无限循环策略的比较:

function loginf() {
  console.log(1+1);
  process.nextTick(loginf);
}
loginf();

这个想法是用来遵从事件循环,并且(大概)允许GC完成它的事情。

由于Node.js v0.10已经发布,在调用递归回调时,应该将其作为首选,而不是
process.nextTick

function loginf() {
  console.log(1+1);
  setImmediate(loginf);
}
loginf();

这段代码的内存消耗一直很低(经过一些研究后,我无法确切地找出为什么节点在没有GC的情况下会消耗越来越多的内存。一般来说,在node.js中使用任何类型的无限循环都是个坏主意。我们必须理解node.js脚本实际上已经在运行一个事件循环(可能是无限的)在执行输入脚本之后,因此没有理由在等待事件发生时模拟这样的循环。(来自nodejs.org)“节点在执行输入脚本之后只进入事件循环。当没有更多要执行的回调时,节点退出事件循环。[…]事件循环对用户隐藏。”@WTK我知道一个事件循环或多或少是一个无限循环,但这个构造并不是为了让循环保持活动状态;我在编写守护进程时意外发现了它。这段代码还有其他变体,例如使用setInterval重复调用回调,延迟1ms,这也会导致这个问题。我在Python下尝试了类似的代码还有Ruby,它们都有一个稳定的内存占用空间。关于触发此问题的其他可能方式,您是对的,但它们基本上都阻止了无限循环。我非常确定,每个经过良好测试、稳定、长期运行的库都依赖于node.js“native”事件循环不在手动创建的某种阻塞无限循环上。无论如何,我希望有人能解释一下在这种无限循环中发生了什么,以及为什么内存使用量不断增加。@WTK我同意你的观点;阻塞调用也会影响执行速度——大约是可比Python或Ruby代码的1/6。我是w看看它是否足够稳定和安全,可以在生产中使用。你应该将其作为一个bug进行归档。因此,基本上GC只在事件循环时发生?@Matty GC实际上会在堆增长时发生很多次。但是它不能收集活的东西:写请求辅助结构由out在内部保存在调用写回调之前放置流…这永远不会发生。因为事件循环被阻止,所以输出流不理解他从底层请求的IO操作已经完成,并且不再需要这些结构。这是内存的一个巨大改进,它也比IIRC快一点。我很惊讶setInterval也不是这样工作的;短延迟调用函数会导致相同的内存泄漏。我想知道这些是否是Node中的设计问题。@Matty:的文档中说“这不是setTimeout(fn,0)的简单别名,效率更高”,所以它看起来像是一个明确的设计选择。