NodeJS 无限循环内存消耗
我不知道这是否是 Node 或 V8 的错误,但如果我运行以下代码,节点进程会泄漏内存。 GC 似乎从未启动,并且在几秒钟内就消耗了超过 1GB 的内存。这是意想不到的行为。我错过了什么吗?
代码如下:
for(;;) { console.log(1+1); }
显然,这有点人为的情况,但我可以看到长期运行的进程永远不会释放内存的问题。
编辑:我尝试了 v0.5.10(不稳定)和 v0.4.12(稳定),不稳定版本的表现稍好一些——稳定版本只是停止输出到控制台,但继续消耗内存,而稳定版本继续执行并消耗内存而不会暂停。
I don't know if this is a bug with Node or V8, but if I run the following code the node process leaks memory. The GC never seems to kick in and in a few seconds it's consuming >1GB of memory. This is unexpected behavior. Am I missing something?
Here's the code:
for(;;) { console.log(1+1); }
Obviously, this is a little bit of a contrived situation, but I can see an issue with a long-running process that would never free memory.
Edit: I tried both with v0.5.10 (unstable) and v0.4.12 (stable) and the unstable version performs a little bit better---the stable version just stops outputting to the console but continues to consume memory, whereas the stable version continues executing and consuming memory without pause.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您通过从不返回来阻止 node.js 事件循环。
当您向流写入内容时,node.js 会异步执行此操作:它发送写入请求,在流的内部数据结构中对有关已发送请求的信息进行排队,并等待通知其完成的回调。
如果您阻塞事件循环,则永远不会调用回调(因为永远不会处理传入事件)并且流中排队的辅助数据结构永远不会被释放。
如果您通过不断地使用 nextTick/setInterval/setTimeout 安排自己的事件来“超载”事件循环,则可能会发生同样的情况。
You are blocking node.js event loop by never returning to it.
When you write something to a stream node.js does that asynchronously: it sends the write request, queues information about sent request in the stream's internal data-structures and awaits the callback that would notify it about the completion.
If you are blocking event loop the callback will never be called (because incoming events are never processed) and auxiliary data structures queued in the stream will never be freed.
The same can probably happen if you "overload" event loop by constantly scheduling your own events with nextTick/setInterval/setTimeout.
@VyacheslavEgorov 的答案似乎是正确的,但我猜推迟事件循环可以解决问题。您可能想将无限
for-loop
与此无限循环策略进行比较:想法是使用
process.nextTick(cb)
推迟事件循环并(可能)允许 GC 执行其操作。The answer by @VyacheslavEgorov seems right on but I would guess that deferring to the event loop would solve the problem. You might want to compare how your infinite
for-loop
compares to this infinite looping strategy:The idea is to use
process.nextTick(cb)
to defer to the event loop and (presumably) allow the GC to do its thing.随着 Node.js v0.10 的发布,
setImmediate
应作为首选,而不是process.nextTick
。在我的计算机上运行大约 15 分钟后,这段代码的内存消耗保持在较低水平(<10MB)。
相反,运行无限
for 循环
会导致内存泄漏,并且process.nextTick
引发超过最大调用堆栈大小
错误。另请查看此问答:setImmediate 与 nextTick
As Node.js v0.10 has been released,
setImmediate
should be used as the first choice instead ofprocess.nextTick
when calling the recursive callback.The memory consumption of this chunk of code kept low ( <10MB ) after running for about 15 mins on my computer.
On the contrary, Running the infinite
for loop
caused memory leek and theprocess.nextTick
throwed anMaximum call stack size exceeded
error.Check this Q&A also: setImmediate vs. nextTick