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

Kam*_*l Z 18 javascript garbage-collection memory-leaks node.js

我已经对我的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);

}
Run Code Online (Sandbox Code Playgroud)

redisClient每秒发出一对'message'事件.这意味着initRequest经常调用函数.每次request在内存中创建对象,并且函数onSuccess绑定到其"成功"事件.

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

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

我用pmap来测试两种情况(比较.on.once另外一种情况,这里不值得一提),我没有发现很大的不同.

在此输入图像描述

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

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

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

Sim*_*olt 5

1:是的:-)

2:通常,在使用事件侦听器时泄漏内存是因为正在发出的对象保持对它的引用,因此防止了正在侦听的对象被垃圾回收.

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

旁注:我不知道内部的内容redisClient,RequestObject但对我而言request,一旦initRequest函数完成,它看起来就像垃圾收集一样,可能在它的任何监听器被调用之前.