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

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

一切似乎没问题,在低stream量本地testing显示,gc正确释放内存。 但是,如果在stream量大的stream量服务器上,它不会。

所以我尝试使用的expose-gc选项,并添加强制gc到每一个断开连接,现在我发现内存不再泄漏,或者它甚至每一次泄漏?

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

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

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

来源:StrongLoop博客

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

当使用事件监听器时,内存泄漏是相当普遍的,并且是由于事件发送器(也是对象)保持引用而阻止正在监听的对象被垃圾收集的情况引起的。

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

为了find代码中存在的对象的真实原因,我会检查连接的结尾,确保没有指针保持活动状态。 另外,在某些情况下,V8不会在每次使用时创build一个函数的实例,这可能就是这种情况。 如果两者合并,则分配的内存将继续堆栈callback的实例。

在两个小垃圾收集中存活的对象被提升为“旧空间”。旧空间是在完整的GC(主垃圾收集周期)中收集的垃圾,其频率较低。 我认为这是一个遥不可及的过程,但是可以考虑select比扫描周期更快的分配,因此当您手动触发垃圾回收时,会触发一个完整的GC周期。

为了确保快速的对象分配,短暂的垃圾收集暂停,“无内存碎片V8”采用了世界末日,准确的垃圾收集器。 当执行完整的垃圾回收循环时,V8本质上会停止程序的执行。

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

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

强制垃圾收集后,每当堆使用超过256MB的一切工作正常小时结束。 GC使用后,从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); 

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