循环 await Promise.all 内存泄漏

Posted

技术标签:

【中文标题】循环 await Promise.all 内存泄漏【英文标题】:Looping over await Promise.all memory leak 【发布时间】:2018-05-13 06:07:29 【问题描述】:

我运行了超过 500 000 个 uid 以通过承诺 (promiseUserData(uid)) 获取它们的关联数据。由于某种原因,内存使用量没有在循环之间清除。

每个循环使用大约 4mb 的数据,并且不会从内存中清除。

我不知道如何解决这个问题。 Promise pooling 也会导致这个问题。

我们将不胜感激。

谢谢

for (var i = 0; i <= numPasses; i++) 
    var subset = uids.splice(0, 1000);

    var userDataArray = [];

    var promises = [];
    subset.map((uid) => 
        promises.push(promiseUserData(uid).then((userData) => 
            if (userData) 
                userDataArray.push(userData);
            
        ));
    );

    await Promise.all(promises).catch((err) => 
        console.log('Error in Promises.all: ', err);
    );

【问题讨论】:

没有从内存中清除。 -> 你如何衡量它?你说的是哪个时间跨度?还剩多少内存? (导致某些 GC 仅在必要时停止世界) 我用 memwatch-next 和 process.memoryUsage().heapUsed 测量了这个。这段代码在 nodejs 上运行,我也手动调用了 GC,但这似乎没有帮助。 如果你在for循环中使用let而不是var呢? var 是函数作用域,let 是块作用域,可能使用let 会清除promises 数组,不知道为什么重新分配它不会清除内存。 @HMR 我已经更新了我的代码,只使用 let 和 const 但没有这样的运气。将尝试不同的循环方法。 @JamesBarnes 您是否尝试过我在下面的答案中发布的方法? 【参考方案1】:

您为每次迭代一次创建 1000 个承诺。

我不完全确定您在尝试什么,但我可以想象您正在寻找类似 @​​987654321@ 的东西。这是处理具有一组并发性的许多 Promise 的便捷方式。可能您已经在该循环内使用 splice 以批量处理您的 Promise。

这种方法需要你安装和导入bluebird:

const userDataArray = [];
try 
  await Bluebird.map(uids, async (uid) => 
    const userData = await promiseUserData(uid);
    if (userData)  userDataArray.push(userData); 
  ,  concurrency: 100 )
 catch (err) 
  console.log('Error in Promises.all: ', err);

【讨论】:

以上是关于循环 await Promise.all 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

await 与 Promise.all 结合使用

await Promise.all() 和多个 await 之间有啥区别?

Promise.all() 与等待

async/await实现Promise.all()

如何用 Promise.all 替换多个 async/await 调用?

promise,async await,try catch的问题整理