node.js v8垃圾收集似乎没有触发

时间:2015-02-04 12:09:15

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

我很困惑,因为我的应用程序正在泄漏内存。它是一个tcp服务器,每分钟处理数十万个数据包。我检查了代码,改进了代码并分析了内存。

一切似乎都没问题,以低流量在本地测试实际上表明gc正确释放了内存。但是当它在现场繁忙的交通服务器上时它并没有。

所以我尝试使用expose-gc选项并将强制gc添加到每次断开连接,现在我发现内存不再泄漏,或者是否每次都泄漏?

所以,我的结论是gc没有激活。我的服务器有3GB内存,应用程序在几个小时内就可以吃掉2.8GB内存。

现在使用强制gc,应用程序不再泄漏。它维持大约200MB的内存。

所以,我的问题,为什么没有触发gc?

2 个答案:

答案 0 :(得分:2)

Source: StrongLoop Blog

  

垃圾收集解决的基本问题是识别死亡   无法访问的内存区域(无法访问的对象/垃圾)   通过一些来自现实对象的指针链。一旦   确定后,这些区域可以重新用于新的分配或   释放回操作系统

使用事件侦听器时内存泄漏是很常见的,并且是由于事件发射器(也是对象)保持对它的引用而导致正在侦听的对象被垃圾收集的情况引起的。

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

为了找到代码中存活对象的真正原因,我要检查连接结束并确保没有指针处于活动状态。 此外,在某些情况下,V8不会在每次使用时创建函数的实例,这可能就是这种情况。如果两者合并,则分配的内存将继续堆叠回调实例。

  

促进了两个小垃圾收集中存活的对象   到了“旧空间”。旧空间是垃圾收集全GC(专业   垃圾收集周期),这是不常见的。我假设这个   是远远不够,但你选择分配比扫地更快   可能会考虑周期,因此当你触发垃圾时   手动收集,触发完整的GC循环。

     

确保快速对象分配,短暂的垃圾收集暂停,以及   “没有内存碎片V8”采用了一个世界,   世代,准确,垃圾收集器。 V8基本上停止了   执行完整的垃圾收集周期时执行程序。

这可以解释为什么当V8被强制进行垃圾清理时内存不会泄漏。

答案 1 :(得分:0)

我注意到垃圾收集没有发生同样的问题。测试我的服务器将相同的内容(通过反应呈现)重复地反映到测试脚本内存将在一个小时左右耗尽。此AWS实例仅具有1GB RAM。

每当heapUsed超过256MB时强制进行垃圾回收,一切都可以正常工作几个小时。 heapUsed在GC之后从大约150MB振荡到略高于256MB。

与此同时,heapTotal最终稳定在340MB左右。

我的结论是我的服务器没有泄漏内存,垃圾收集没有按预期发生。

以下是我的工作:

setInterval (function() {
    let mu = process.memoryUsage();
    console.log('heapTotal:',  mu.heapTotal, 'heapUsed:', mu.heapUsed);
    if (mu.heapUsed > 256 * 1024 * 1024) {
        console.log('Taking out the garbage');
        global.gc();
    }
}, 1000 * 60);

在每次请求后检查内存可能会更好。