【问题标题】:nodejs setTimeout memory leak?nodejs setTimeout内存泄漏?
【发布时间】:2013-04-10 23:06:13
【问题描述】:

v0.10.4

这是导致内存使用量不断增加的简单循环:

function redx(){
      setTimeout(function(){ redx() },1000);
      console.log('loop');
}

redx();

我做错了什么??

编辑

好的,刚刚尝试了在范围内引用超时对象的建议,似乎垃圾收集确实在大约 40 秒后启动,这是来自 TOP 的缩写日志:

3941 根 20 0 32944 7284 4084 S 4.587 3.406 0:01.32 节点
3941 根 20 0 32944 7460 4084 S 2.948 3.489 0:01.59 节点
3941 根 20 0 32944 7516 4084 S 2.948 3.515 0:01.68 节点
3941 根 20 0 33968 8400 4112 S 2.948 3.928 0:02.15 节点
3941 根 20 0 33968 8920 4112 S 3.275 4.171 0:02.98 节点
3941 根 20 0 33968 8964 4112 S 2.948 4.192 0:03.07 节点
3941 根 20 0 33968 9212 4112 S 2.953 4.308 0:03.16 节点
3941 根 20 0 33968 9212 4112 S 2.953 4.308 0:03.25 节点
3941 根 20 0 33968 9212 4112 S 3.276 4.308 0:03.35 节点
3941 根 20 0 33968 9212 4112 S 2.950 4.308 0:03.44 节点

【问题讨论】:

  • 难以置信,我昨天一直在想。我的猜测是 Node 不会收集匿名函数的闭包。
  • 你正在使用什么操作系统?
  • 我在 ARCH 下测试这个。

标签: node.js memory


【解决方案1】:

实际上,我认为这可能正是 V8 垃圾收集器的工作方式。

在我的系统上,节点堆往往会增加到 48 MB,然后稳定下来,所以我认为如果你让程序长时间运行,内存消耗最终会稳定下来。

您可以通过使用 V8 命令行选项之一启动节点来获得有关 GC 何时/如何启动的信息:--trace_gc 标志。

在您第一次尝试使用 Redis 时,您在每次调用时都系统地连接/断开与 Redis 的连接。这往往会产生垃圾。您应该打开一次连接并多次使用它。尽管如此,即使我这样做,内存消耗也趋于稳定。以下是 Redis 示例中内存消耗的演变:

// something close to your initial function (when Redis was still in the picture)
function redx(){
    var client = redis.createClient();
    client.get("tally", function(err, reply) {
        client.quit();
    });
    setTimeout(function(){ redx() }, 50 );
}

这里,60MB后的稳定似乎相当明显。

【讨论】:

  • 谢谢,是的,最初我认为这是 redis / memcache 的问题,但在将代码剥离到最低限度后,我发现只是 setTimeout 导致了这个泄漏。我一直打开一个新连接的原因是,它可能会运行好几个月,我不确定在这段时间内保持打开一个 localhost 连接是否可靠。
  • 我可以确认上图。 Nodejs 似乎在一段时间后稳定了它的内存消耗。这在大多数 GC 中非常典型。我什至通过在 setTimeout 循环中生成一个调用 redx() 的隔离范围来获得相同的结果。我也通过调用 setTimeout(redx.bind(null), 50); 获得了相同的图表。我在上面的例子中有一个猜测,var client = ... 在下一个循环之后变得无法访问,所以它会在一段时间后收集垃圾,所以内存泄漏也不应该适用。它可能会向 Redis 产生 Mem Leak,但这已不在讨论范围内。
【解决方案2】:

不知道为什么,但显然如果你在函数 nodejs 的范围内引用超时对象,就会正确地进行垃圾收集。

function redx(){
      var t = setTimeout(function(){ redx() },50);
      console.log('hi');
}

redx();

【讨论】:

  • 谢谢,我刚刚测试了您的代码,不幸的是,它并没有解决问题,而且我没有看到内存消耗有任何明显差异。
  • 更正,我刚刚又看了一遍,内存使用量最初确实不断增加,然后在大约 40 秒后达到峰值!
  • 奇怪,我可以清楚地看到内存使用量增加,然后恢复到初始值(我猜那是 gc 启动的时候)
  • 准实时评论系统问题。请翻转 cmets #3 和 #2 的顺序 ;)
  • 我也有可能由 setTimeout 引起的内存泄漏。只是很难发现它。我正在使用 node-memwatch 并且只是推送了更改的代码。到目前为止,还没有检测到泄漏。希望它会奏效。
猜你喜欢
  • 1970-01-01
  • 2021-01-25
  • 2016-04-22
  • 2021-01-31
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多