为什么 Node.js 中的全局数组会导致内存泄漏?
Why does a global array in Node.js cause a Memory Leak?
我想了解 Node.js 中的垃圾收集是如何工作的。
创建了一个大数组并全局存储。在跟踪 Heap Usage 时,我发现一旦创建了数组,Heap Usage 就会急剧上升。难怪,因为数组很大。
但似乎垃圾收集器并没有删除数组——无论我等多久,堆使用率都保持不变。垃圾收集器认为,数组还需要吗?
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)
```
垃圾收集器并非一直都在收集。仅当您的计算机 运行 内存不足时。
试试这个 post 并手动触发垃圾收集器。还会有内存泄漏吗?
How to request the Garbage Collector in node.js to run?
此外,该数组仍然被引用,如果您将它设置为 null 某处它可能会被收集。
该数组仍在模块函数闭包中引用,因此无法进行垃圾回收:
// 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 并强制 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 中的垃圾收集是如何工作的。
创建了一个大数组并全局存储。在跟踪 Heap Usage 时,我发现一旦创建了数组,Heap Usage 就会急剧上升。难怪,因为数组很大。 但似乎垃圾收集器并没有删除数组——无论我等多久,堆使用率都保持不变。垃圾收集器认为,数组还需要吗?
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)
```
垃圾收集器并非一直都在收集。仅当您的计算机 运行 内存不足时。
试试这个 post 并手动触发垃圾收集器。还会有内存泄漏吗?
How to request the Garbage Collector in node.js to run?
此外,该数组仍然被引用,如果您将它设置为 null 某处它可能会被收集。
该数组仍在模块函数闭包中引用,因此无法进行垃圾回收:
// 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 并强制 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)