我想了解Node.js中的垃圾收集是如何工作的。
创建一个大数组并全局存储。在跟踪堆使用情况时,我发现一旦创建了数组,堆使用情况急剧上升。难怪,因为数组是巨大的。但是似乎垃圾收集器并没有删除数组——无论我等待多长时间,堆使用率都保持不变。垃圾回收器是否认为,这个数组仍然是需要的?
let bigArray
setTimeout(function() {
bigArray = new Array(9999999)
}, 5000)
setInterval(function () {
const used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`Usage: ${Math.round(used * 100) / 100} MB`);
}, 1000)
```
该数组仍然在模块函数闭包中被引用,因此不能被垃圾收集:
// Implicit closure created by nodejs
(function(exports, require, module, __filename, __dirname) {
let bigArray
setTimeout(function() {
bigArray = new Array(9999999)
}, 5000);
setInterval(function () {
// `bigArray` is still in scope here so cannot be garbage collected
// If you set bigArray to undefined it will get GC'd
const used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`Usage: ${Math.round(used * 100) / 100} MB`);
}, 1000);
});
如果你只在setTimeout函数范围内声明变量,它将被GC处理,而不必自己删除引用,例如
// Implicit closure created by nodejs
(function(exports, require, module, __filename, __dirname) {
setTimeout(function() {
let bigArray = new Array(9999999)
}, 5000);
setInterval(function () {
// `bigArray` is not in scope here so it will be GC'd
const used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`Usage: ${Math.round(used * 100) / 100} MB`);
}, 1000);
});
另外,要注意V8在没有内存约束的情况下可能会表现得很懒。
您可以尝试使用——expose-gc和force gc来运行脚本:
node --expose-gc index.js
const forceGC = () => {
if (global.gc) {
global.gc();
} else {
console.warn('No GC hook! Start your program as `node --expose-gc file.js`.');
}
}
let bigArray
setTimeout(function() {
bigArray = new Array(9999999)
}, 5000)
setInterval(function () {
bigArray = undefined;
forceGC();
const used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`Usage: ${Math.round(used * 100) / 100} MB`);
}, 1000)
同样,你可以给节点更少的内存来测试它在内存不足时的行为:
node --max-old-space-size=100 index.js // Give node just 100MB (defaults to 2GB)
垃圾收集器不会一直收集。只有当你的电脑内存快用完的时候。
尝试这篇文章并手动触发垃圾收集器。它还会有内存泄漏吗?
如何请求垃圾收集器在node.js运行?
数组仍然被引用,如果你将它设置为null,它可能会被收集。