繁体   English   中英

由于内存不足而无法完成承诺

[英]unable to complete promises due to out of memory

我有一个脚本可以抓取约1000个网页。 我正在使用Promise.all将它们一起触发,并在完成所有页面后返回:

Promise.all(urls.map(url => scrap(url)))
    .then(results => console.log('all done!', results));

这很不错,很正确,除了一件事-机器由于并发请求而耗尽内存 我使用jsdom进行jsdom ,它很快占用了几个GB的mem,考虑到它实例化了数百个window ,这是可以理解的。

我有个解决办法,但我不喜欢。 也就是说,将控制流更改为不使用Promise.all,而是链接我的诺言:

let results = {};
urls.reduce((prev, cur) =>
    prev
        .then(() => scrap(cur))
        .then(result => results[cur] = result)
        // ^ not so nice. 
, Promise.resolve())
    .then(() => console.log('all done!', results));

这不像Promise.all那样好。它的性能不佳,因为它被链接了,返回的值必须存储起来,以便以后处理。

有什么建议么? 我应该改善控制流程还是应该改善scrap()中的内存使用情况,还是有办法让节点限制内存分配?

您正在尝试并行运行1000个Web剪贴簿。 您将需要选择一个明显少于1000的数字,并且一次只运行N个,这样您就可以减少内存消耗。 您仍然可以使用Promise来跟踪它们何时完成。

蓝鸟的Promise.map()可以通过将并发值作为选项来为您做到这一点。 或者,您可以自己编写。

我有个解决办法,但我不喜欢。 也就是说,将控制流更改为不使用Promise.all,而是链接我的诺言:

您想要的是同时进行N次操作。 排序是一种特殊情况,其中N = 1 ,这通常比并行执行某些操作要慢得多(也许N = 10 )。

这不像Promise.all那样好。它的性能不佳,因为它被链接了,返回的值必须存储起来,以便以后处理。

如果存储的值是内存问题的一部分,则可能必须以任何方式将它们存储在内存之外。 您将不得不分析存储的结果正在使用多少内存。

有什么建议么? 我应该改善控制流程还是应该改善scrap()中的内存使用情况,还是有办法让节点限制内存分配?

使用Bluebird的Promise.map()或自己编写类似的内容。 并行编写最多可进行N次操作并保持所有结果有序的内容不是火箭科学,但要使其正确,需要付出一些努力。 我之前曾在另一个答案中介绍过它,但现在似乎找不到。 我会继续寻找。

在这里找到了我先前的相关答案: 向一个API发出多个请求,每分钟只能处理20个请求

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM