gpt4 book ai didi

Javascript内存泄漏检测

转载 作者:行者123 更新时间:2023-12-02 22:10:59 25 4
gpt4 key购买 nike

我编写了一个非常简单的脚本来查询redis中列表的长度并输出内存使用情况。

随着时间的推移,“堆使用”内存似乎越来越高。

这是否推断内存泄漏,如何更改此代码以防止这种情况?

输出:

[2020-01-02 16:59:09] Queue length > 0
[2020-01-02 16:59:09] Test queue length is 121
[2020-01-02 16:59:09] Heap total: 18.23MB, Heap Used: 8.43MB
[2020-01-02 16:59:11] Queue length > 0
[2020-01-02 16:59:11] Test queue length is 121
[2020-01-02 16:59:11] Heap total: 18.73MB, Heap Used: 8.70MB
[2020-01-02 16:59:13] Queue length > 0
[2020-01-02 16:59:13] Test queue length is 121
[2020-01-02 16:59:13] Heap total: 18.73MB, Heap Used: 8.72MB
...
[2020-01-02 17:03:53] Queue length > 0
[2020-01-02 17:03:53] Test queue length is 121
[2020-01-02 17:03:53] Heap total: 18.73MB, Heap Used: 11.17MB

代码:

const Redis           = require('ioredis');
const redis = new Redis();
const dateformat = require('dateformat');
const log = console.log;


console.log = function () {
let output = ['[',dateformat(new Date(), "yyyy-mm-dd HH:MM:ss")];
output.push(']');
output = [output.join('')]
output = output.concat([].slice.call(arguments));
log.apply(console,
output
);
}

function loop() {
redis.llen('test').then( (queue_length) => {
if (queue_length > 0) {
console.log("Queue length > 0")
}
console.log(`Test queue length is ${queue_length}`)
let m = process.memoryUsage()
console.log(`Heap total: ${(m['heapTotal']/1024/1024).toFixed(2)}MB, Heap Used: ${(m['heapUsed']/1024/1024).toFixed(2)}MB`);
})
}

setInterval(loop, 2000)

编辑:

最终我看到了我只能假设的垃圾收集:

[2020-01-02 17:05:41] Queue length > 0
[2020-01-02 17:05:41] CDR queue length is 121
[2020-01-02 17:05:41] Heap total: 13.73MB, Heap User: 8.63MB

我不确定随着内存持续增加,然后在垃圾收集后下降,是否仍然推断出泄漏。最佳实践是在此 setInterval 循环期间清除变量分配,还是将其留给 GC?

最佳答案

有一些用例需要手动清除指向非常大的数据结构的变量,但大多数情况下,在 Javascript 中,您只需让 GC 完成其工作,并确保不会保留对不存在的大型数据结构的引用。永久变量(在持久作用域中声明的变量,如顶层)不再需要,或者在数组等结构中累积不再需要的数据。

仅供引用,清除对大型数据结构的引用并不会在当时将其从内存中删除 - 它只是在 GC 决定运行时使其符合 GC 的条件(如果没有其他变量指向相同的数据)。

<小时/>

Javascript 中有几种需要留意的情况,它们可能会让人们感到惊讶,这通常是因为 Javascript 中的函数作用域和该作用域中的局部变量在函数本身完成后可以存活很长时间正在执行。

这是一个简单的例子:

function startTimer() {
let bigVar = someGiantDataStructure;
return setInterval(function() {
if (someCondition) {
++bigVar.someProperty;
} else {
// do something else
}
}, 1000);
}

let intervalID = startTimer();

因此,即使 startTimer() 运行并完成,它也会启动间隔计时器,该计时器会继续定期调用其回调。因为理论上回调仍然可能引用 bigVar,所以 bigVar 指向的数据永远不会被垃圾收集,直到有人停止间隔计时器。

因此,如果在处理计时器时发生了某些情况,并且您知道 someCondition 永远不会再为 true,或者永远不会再需要 bigVar 的内容,但是间隔计时器由于其他原因而继续运行,那么执行诸如 bigVar = null; 之类的操作以允许其指向的数据符合垃圾回收条件是有意义的。

关于Javascript内存泄漏检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59558941/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com