我很困惑,因为我的应用程序正在泄漏内存。它是一个tcp服务器,每分钟处理数十万个数据包。我检查了代码,改进了代码并分析了内存。
一切似乎都没问题,以低流量在本地测试实际上表明gc正确释放了内存。但是当它在现场繁忙的交通服务器上时它并没有。
所以我尝试使用expose-gc
选项并将强制gc添加到每次断开连接,现在我发现内存不再泄漏,或者是否每次都泄漏?
所以,我的结论是gc没有激活。我的服务器有3GB内存,应用程序在几个小时内就可以吃掉2.8GB内存。
现在使用强制gc,应用程序不再泄漏。它维持大约200MB的内存。
所以,我的问题,为什么没有触发gc?
答案 0 :(得分:2)
垃圾收集解决的基本问题是识别死亡 无法访问的内存区域(无法访问的对象/垃圾) 通过一些来自现实对象的指针链。一旦 确定后,这些区域可以重新用于新的分配或 释放回操作系统
使用事件侦听器时内存泄漏是很常见的,并且是由于事件发射器(也是对象)保持对它的引用而导致正在侦听的对象被垃圾收集的情况引起的。
因此,在您的代码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);
在每次请求后检查内存可能会更好。