我不知道这是否是Node或V8的错误,但如果我运行以下代码,则节点进程会泄漏内存。 GC似乎永远不会启动,并且在几秒钟内耗费了大约1GB的内存。这是出乎意料的行为。我错过了什么吗?
以下是代码:
for(;;) { console.log(1+1); }
显然,这是一个有点人为的情况,但我可以看到长时间运行过程中永远不会释放内存的问题。
编辑:我尝试了v0.5.10(不稳定)和v0.4.12(稳定版),不稳定版本执行得更好一点---稳定版本只是停止输出到控制台但继续消耗内存,而稳定版本继续执行并消耗内存而不会暂停。
答案 0 :(得分:10)
您通过永远不会返回它来阻止node.js事件循环。
当您向流节点写入内容时.js异步执行此操作:它发送写入请求,在流的内部数据结构中对有关已发送请求的信息进行排队,并等待将通知其完成的回调。
如果阻塞事件循环,则永远不会调用回调(因为从不处理传入事件),并且永远不会释放在流中排队的辅助数据结构。
如果通过使用nextTick / setInterval / setTimeout不断调度自己的事件来“重载”事件循环,则可能会发生同样的情况。
答案 1 :(得分:6)
@VyacheslavEgorov的回答似乎正确,但我猜想推迟到事件循环可以解决问题。您可能想要比较无限for-loop
与此无限循环策略的比较:
function loginf() {
console.log(1+1);
process.nextTick(loginf);
}
loginf();
我的想法是使用process.nextTick(cb)
来推迟事件循环,并且(可能)允许GC完成它的工作。
答案 2 :(得分:5)
当Node.js v0.10已经发布时,setImmediate
应该在调用递归回调时作为第一选择而不是process.nextTick
。
function loginf() {
console.log(1+1);
setImmediate(loginf);
}
loginf();
在我的计算机上运行约15分钟后,此代码块的内存消耗保持较低(<10MB)。
相反,运行无限for loop
引起内存韭菜而process.nextTick
引发了Maximum call stack size exceeded
错误。
同时检查此Q&amp; A:setImmediate vs. nextTick