我正在使用node并考虑在节点中手动运行垃圾收集。这有什么缺点吗?我这样做的原因是看起来节点没有经常运行垃圾收集。有人知道V8在节点中执行垃圾收集例程的频率吗?
谢谢!
答案 0 :(得分:13)
我实际上在使用1GB实例的heroku上运行节点时遇到了同样的问题。
在生产流量上运行节点服务器时,内存会不断增长,直到超出内存限制,导致内存运行缓慢。
这可能是由于应用程序生成了大量垃圾,它主要服务于JSON API响应。但这不是内存泄漏,只是未收集的垃圾。
似乎节点没有优先考虑在我的应用程序的旧对象空间上进行足够的垃圾收集,因此内存会不断增长。
手动运行global.gc()(使用节点--expose_gc启用)每次会减少50MB的内存使用量,并暂停应用程序约400ms。
我最终做的是在一个随机的时间表上手动运行gc(这样heroku实例不会同时执行GC)。这减少了内存使用量并停止了内存配额超出错误。
简化版本将是这样的:
function scheduleGc() {
if (!global.gc) {
console.log('Garbage collection is not exposed');
return;
}
// schedule next gc within a random interval (e.g. 15-45 minutes)
// tweak this based on your app's memory usage
var nextMinutes = Math.random() * 30 + 15;
setTimeout(function(){
global.gc();
console.log('Manual gc', process.memoryUsage());
scheduleGc();
}, nextMinutes * 60 * 1000);
}
// call this in the startup script of your app (once per process)
scheduleGc();
您需要在暴露垃圾收集的情况下运行您的应用程序:
node --expose_gc app.js
答案 1 :(得分:3)
我知道这可能对OP的帮助有点迟缓,但我想我会合作我最近使用Node JS内存分配和垃圾收集的经验。
我们目前正在研究在raspberry pi 3上运行的节点JS服务器。由于内存不足,它们经常会崩溃。我最初认为这是一个内存泄漏,经过一周半的搜索我的代码并且没有任何结果,我认为这个问题可能因为Node JS分配的内存比Rpi3上的内存更多而更加严重。它在进行GC之前的过程。
我一直使用以下命令运行服务器的新实例:
'node server.js --max-executable-size = 96 --max-old-space-size = 128 --max-semi-space-size = 2'
这有效地限制了允许节点在本地计算机上占用的空间总量,并且更频繁地强制执行垃圾收集。到目前为止,我们看到了内存的不断使用,它向我确认我的代码最初没有泄漏,而是节点分配的内存比可能的多。
编辑:此处的链接更具体地概述了我正在处理的问题。
- nodejs decrease v8 garbage collector memory usage - https://github.com/nodejs/node/issues/2738
答案 2 :(得分:0)
V8当他认为垃圾收集时,他会进行垃圾收集。没有固定的延迟。您可以阅读本文以了解垃圾收集V8:https://strongloop.com/strongblog/node-js-performance-garbage-collection/
无论如何,在项目中手动运行垃圾收集器是一个坏主意,因为它完全阻止了节点进程。所以在垃圾收集过程中,你的程序不会处理任何请求。