【发布时间】:2011-12-15 14:55:36
【问题描述】:
我不知道这是 Node 还是 V8 的错误,但如果我运行以下代码,节点进程会泄漏内存。 GC 似乎永远不会启动,并且在几秒钟内它会消耗超过 1GB 的内存。这是意外行为。我错过了什么吗?
代码如下:
for(;;) { console.log(1+1); }
显然,这有点人为的情况,但我可以看到一个长期运行的进程永远不会释放内存的问题。
编辑:我尝试了 v0.5.10(不稳定)和 v0.4.12(稳定),不稳定版本的性能稍微好一点——稳定版本只是停止输出到控制台但继续消耗内存,而稳定版继续执行和消耗内存,没有暂停。
【问题讨论】:
-
经过一些研究,我无法准确找出为什么节点在没有 GC 的情况下会消耗越来越多的内存。一般来说,在 node.js 中使用任何类型的无限循环都是 bad 的想法。必须了解 node.js 脚本在执行输入脚本后实际上已经在运行一个事件循环(可能是无限的),因此没有理由在等待某事发生时模拟这样的循环。 (来自 nodejs.org)“节点只是在执行输入脚本后进入事件循环。当没有更多回调要执行时,节点退出事件循环。[...] 事件循环对用户隐藏。”
-
@WTK 我知道事件循环或多或少是一个无限循环,但这种结构并不是为了保持循环存活;我在编写守护程序时偶然发现了它。此代码还有其他变体,例如使用 setInterval 以 1 毫秒的延迟重复调用回调也会导致此问题。我在 Python 和 Ruby 下尝试了类似的代码,它们的内存占用都小于 10MB。我可以想象,在负载下长时间运行的守护进程会发生类似的内存泄漏,尽管我还没有测试过。
-
您对触发此问题的其他可能方式是正确的,但它们基本上都是阻塞无限循环。我很确定每个经过良好测试、稳定、长时间运行的库都依赖于 node.js“本机”事件循环,而不是手动创建的某种阻塞无限循环。无论如何,我希望有人能阐明这种无限循环中发生了什么,以及为什么内存使用量不断增加。
-
@WTK 我同意你的看法;阻塞调用也会影响执行速度——大约是可比较的 Python 或 Ruby 代码的 1/6。我想知道在看到这个之后它是否足够稳定和安全,可以在生产中使用。
-
您应该将此作为错误提交。
标签: javascript node.js memory-leaks infinite-loop v8