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

Mat*_*tty 14 javascript memory-leaks v8 infinite-loop node.js

我不知道这是不是Node或V8的错误,但如果我运行以下代码,节点进程会泄漏内存.GC似乎永远不会启动,并且在几秒钟内消耗了大约1GB的内存.这是出乎意料的行为.我错过了什么吗?

这是代码:

for(;;) { console.log(1+1); }
Run Code Online (Sandbox Code Playgroud)

显然,这是一个有点人为的情况,但我可以看到一个永远不会释放内存的长期运行过程的问题.

编辑:我尝试了v0.5.10(不稳定)和v0.4.12(稳定版),不稳定版本执行得更好---稳定版本只是停止输出到控制台但继续消耗内存,而稳定版本继续执行和消耗内存而不会暂停.

Vya*_*rov 11

您通过永远不返回它来阻止node.js事件循环.

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

如果阻塞事件循环,则永远不会调用回调(因为从不处理传入事件),并且永远不会释放在流中排队的辅助数据结构.

如果通过使用nextTick/setInterval/setTimeout不断调度自己的事件来"重载"事件循环,则可能会发生同样的情况.

  • @Matty GC实际上会在堆增长时发生很多次。但是它不能收集“有效”的东西:写请求辅助结构由输出流在内部保留,直到调用写后回调为止……这永远不会发生。因为事件循环被阻止,所以输出流无法理解他从底层请求的IO操作已完成,并且不再需要这些结构。 (2认同)

mae*_*ics 6

@VyacheslavEgorov的回答似乎正确,但我猜这推迟到事件循环将解决问题.您可能想要比较无限for-loop与无限循环策略的比较:

function loginf() {
  console.log(1+1);
  process.nextTick(loginf);
}
loginf();
Run Code Online (Sandbox Code Playgroud)

这个想法是用来process.nextTick(cb)推迟事件循环,并且(可能)允许GC做它的事情.


小智 5

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

function loginf() {
  console.log(1+1);
  setImmediate(loginf);
}
loginf();
Run Code Online (Sandbox Code Playgroud)

在我的计算机上运行约15分钟后,此代码块的内存消耗保持较低(<10MB).

相反,运行无限for loop造成内存韭菜和process.nextTick倒掉的Maximum call stack size exceeded错误.

还要检查此问答:setImmediate与nextTick