由于内存不足无法完成承诺
unable to complete promises due to out of memory
我有一个脚本可以抓取大约 1000 个网页。我正在使用 Promise.all 将它们一起触发,当所有页面都完成后 returns:
Promise.all(urls.map(url => scrap(url)))
.then(results => console.log('all done!', results));
这很好而且正确,除了一件事 - 由于并发请求,机器 内存不足 。我使用 jsdom
进行报废,它很快就会占用几 GB 的内存,考虑到它实例化了数百个 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 个并行的网络抓取。您将需要选择一些明显小于 1000 且 运行 一次仅选择 N 的数字,以便在这样做时消耗更少的内存。您仍然可以使用承诺来跟踪它们何时完成。
Bluebird's Promise.map()
可以通过将并发值作为选项传递来为您做到这一点。或者,您可以自己编写。
I have an idea to fix but I don't like it. That is, change control
flow to not use Promise.all, but chain my promises:
你想要的是同时进行N个操作。排序是一种特殊情况,其中 N = 1
通常比并行执行其中一些(可能 N = 10
)要慢得多。
This is not as good as Promise.all... Not performant as it's chained,
and returned values have to be stored for later processing.
如果存储值是您内存问题的一部分,您可能不得不以任何方式将它们存储在内存之外的某个地方。您将不得不分析存储的结果使用了多少内存。
Any suggestions? Should I improve the control flow or should I improve
mem usage in scrap(), or is there a way to let node throttle mem
allocation?
使用Bluebird's Promise.map()
或者自己写类似的东西。编写最多 运行 并行操作并保持所有结果有序的东西不是火箭科学,但要使其正确需要一些工作。我之前在另一个答案中介绍过它,但现在似乎无法找到它。我会继续寻找。
在这里找到我之前的相关答案:
我有一个脚本可以抓取大约 1000 个网页。我正在使用 Promise.all 将它们一起触发,当所有页面都完成后 returns:
Promise.all(urls.map(url => scrap(url)))
.then(results => console.log('all done!', results));
这很好而且正确,除了一件事 - 由于并发请求,机器 内存不足 。我使用 jsdom
进行报废,它很快就会占用几 GB 的内存,考虑到它实例化了数百个 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 个并行的网络抓取。您将需要选择一些明显小于 1000 且 运行 一次仅选择 N 的数字,以便在这样做时消耗更少的内存。您仍然可以使用承诺来跟踪它们何时完成。
Bluebird's Promise.map()
可以通过将并发值作为选项传递来为您做到这一点。或者,您可以自己编写。
I have an idea to fix but I don't like it. That is, change control flow to not use Promise.all, but chain my promises:
你想要的是同时进行N个操作。排序是一种特殊情况,其中 N = 1
通常比并行执行其中一些(可能 N = 10
)要慢得多。
This is not as good as Promise.all... Not performant as it's chained, and returned values have to be stored for later processing.
如果存储值是您内存问题的一部分,您可能不得不以任何方式将它们存储在内存之外的某个地方。您将不得不分析存储的结果使用了多少内存。
Any suggestions? Should I improve the control flow or should I improve mem usage in scrap(), or is there a way to let node throttle mem allocation?
使用Bluebird's Promise.map()
或者自己写类似的东西。编写最多 运行 并行操作并保持所有结果有序的东西不是火箭科学,但要使其正确需要一些工作。我之前在另一个答案中介绍过它,但现在似乎无法找到它。我会继续寻找。
在这里找到我之前的相关答案: