Node.js(v8)垃圾收集器如何工作?

时间:2014-01-16 13:20:23

标签: javascript node.js memory-leaks garbage-collection

我已经对我的node.js应用程序进行了一些测试,以查找我的代码应该执行的内存泄漏。我运行脚本,在我看来应该泄漏内存,但我对结果感到惊讶。

redisClient.on('message', initRequest);


function onSuccess(self, json){

  console.dir(json);

}


function initRequest(channel, message){

  var request = new RequestObject({

    redisMessage: message

  });

  request.on('success', onSuccess);

}

redisClient每秒发出几个“消息”事件。这意味着经常调用initRequest函数。每次request对象在内存中创建,函数onSuccess绑定到其“成功”事件。

我假设(但在这里我可能是错的),就侦听器(在这种情况下为onSuccess)绑定到此对象而言,它不能被垃圾收集。然后我想,内存使用会增长,因为内存不会被释放。

作为这种潜在泄漏的解决方案,我想使用.once而不是.on,因为这将取消绑定侦听器和对象可能被垃圾收集。

我已经使用 pmap 来测试两个方案(比较.on.once以及另一个不值得一提的方案),而我还没有发现了很大的不同。

enter image description here

总结一下,我有两个问题:

  1. 这种正常的GC行为是在某些时间间隔内清除内存,还是在达到某些威胁后而不是连续清洁时?

  2. 我是否正确地假设带有.on的示例代码应该泄漏内存,我在内存消耗图上没有看到?

2 个答案:

答案 0 :(得分:5)

1:是: - )

2:一般情况下,使用事件监听器时内存泄漏是因为正在发出的对象保持对它的引用,因此阻止了正在侦听的对象。

因此,在您的代码中,onSuccess对象将引用request函数。但是,onSuccess只是一个被重用作所有请求对象的侦听器的函数,因此不会导致内存堆积。

旁注:我不知道redisClientRequestObject的内部结构,但对我来说,request看起来像initRequest一样就可以进行垃圾收集了{{1}函数完成,可能在调用任何侦听器之前。

答案 1 :(得分:2)

据我所知,请求对象应该只存在于initRequest函数中,并且应该在函数终止时标记为垃圾回收。