Javascript 使用承诺时Typescript内存泄漏

Javascript 使用承诺时Typescript内存泄漏,javascript,typescript,Javascript,Typescript,用Typescript编写这段代码 const f = async function() { return 1+1; }; let memory = process.memoryUsage(); let i = 0; while (i < 100000) { let result = await f().then(function(res) {}).catch(function() {}); i++; } let memory2 = process.memoryU

用Typescript编写这段代码

const f = async function() {
    return 1+1;
};

let memory = process.memoryUsage();
let i = 0;
while (i < 100000) {
    let result = await f().then(function(res) {}).catch(function() {});
    i++;
}
let memory2 = process.memoryUsage();
console.log(memory2.heapUsed - memory.heapUsed);
迭代次数越多,两点之间的重叠就越大

通过适当地减少方法,而不是使用承诺,而是使用简单的方法,使用的堆变得稳定,即使我迭代了一百万次也不会改变

const f = function() {
    return 1+1;
};

let memory = process.memoryUsage();
let i = 0;
while (i < 200000) {
    let r = f();
    i++;
}
let memory2 = process.memoryUsage();
console.log(memory2.heapUsed - memory.heapUsed);

有人能解释一下内存泄漏的确切位置吗?什么地方是永久性地保留在内存中的点?

我相信如果你设置一个1秒或2秒的设置超时并结束它,然后再次检查你的内存使用情况,你会发现你的内存再次下降。因为您在同步循环中使用异步函数,所以这些迭代都存储在内存中,同时等待堆栈清除,直到代码执行完毕后才会发生,包括内存检查。

我相信如果你设置一个1秒或2秒的超时时间并结束它,然后再次检查内存使用情况,你会发现你的内存再次下降。因为您在同步循环中使用异步函数,所以这些迭代都存储在内存中,同时它们等待堆栈清除,这在代码执行完成(包括内存检查)之前是不会发生的

有人能解释一下内存泄漏的确切位置吗

内存使用不是内存泄漏。如果内存可以被垃圾回收,它就不会泄漏。您的示例根本不足以保证GC运行

以下代码强制运行gc,不推荐使用!:

const f = async function () {
    return 1 + 1;
};

async function main() {
    let memory = process.memoryUsage();
    let i = 0;
    while (i < 100000) {
        let result = await f().then(function(res) {}).catch(function() {});
        i++;
    }
    console.log('before', process.memoryUsage().heapUsed - memory.heapUsed);
    global.gc();
    console.log('after', process.memoryUsage().heapUsed - memory.heapUsed);
}

main();
如果您运行它,您会注意到在gc运行之后,内存实际上从应用程序的开始就减少了。示例运行:

有人能解释一下内存泄漏的确切位置吗

内存使用不是内存泄漏。如果内存可以被垃圾回收,它就不会泄漏。您的示例根本不足以保证GC运行

以下代码强制运行gc,不推荐使用!:

const f = async function () {
    return 1 + 1;
};

async function main() {
    let memory = process.memoryUsage();
    let i = 0;
    while (i < 100000) {
        let result = await f().then(function(res) {}).catch(function() {});
        i++;
    }
    console.log('before', process.memoryUsage().heapUsed - memory.heapUsed);
    global.gc();
    console.log('after', process.memoryUsage().heapUsed - memory.heapUsed);
}

main();
如果您运行它,您会注意到在gc运行之后,内存实际上从应用程序的开始就减少了。示例运行:


不确定是不是漏水。当你打印统计数据时,你的函数还没有退出,所以没有得到GC'd。总有一天会被收集起来的。不确定是不是泄漏。当你打印统计数据时,你的函数还没有退出,所以没有得到GC'd。它会在某个时候被收集起来。澄清一下:这里不一定有漏洞。泄漏就像维护对那些异步函数中变量的访问,这将阻止GC清除与这些作用域相关的内存。因此,如果这个过程(而不是使用这个简单的调用)管理多个操作,并且我需要在一段时间内维护这个过程,比如说导出,会发生什么?如果我想到达进程的末尾,这意味着要管理数千个实体,但是GC在进程完成之前不会真正完成它的工作,那么我如何才能真正强制GC完成这项工作呢?毕竟添加了3秒的setTimeout,并且内存使用量永远不会下降内存统计数据到底是什么?我刚刚用你的同步代码运行了一些测试,发现我用来循环的变量正是导致内存膨胀的原因。GC将搜索所有已分配的内存,并查看在JS范围外无法访问的内容,然后删除这些内容。如果在循环中有一个异步进程在运行,那么只要该进程仍处于活动状态,GC就不能消除该迭代范围内存储的任何变量,因为如果异步任务在完成之前引用了这些变量,则这些变量必须可用。您可以尝试使用wait来确保在循环进入下一个迭代之前退出任务。泄漏就像维护对那些异步函数中变量的访问,这将阻止GC清除与这些作用域相关的内存。因此,如果这个过程(而不是使用这个简单的调用)管理多个操作,并且我需要在一段时间内维护这个过程,比如说导出,会发生什么?如果我想到达进程的末尾,这意味着要管理数千个实体,但是GC在进程完成之前不会真正完成它的工作,那么我如何才能真正强制GC完成这项工作呢?毕竟添加了3秒的setTimeout,并且内存使用量永远不会下降内存统计数据到底是什么?我刚刚用你的同步代码运行了一些测试,发现我用来循环的变量正是导致内存膨胀的原因。GC将搜索所有已分配的内存,并查看在JS范围外无法访问的内容,然后删除这些内容。如果您有一个异步进程正在运行 在您的循环中,只要该过程仍然处于活动状态,GC就无法消除该迭代范围内存储的任何变量,因为如果异步任务在完成之前引用了这些变量,则这些变量必须可用。您可以尝试使用wait确保在循环进入下一个迭代之前退出任务。