我正在从MongoDB中解析一个相当大的数据集(大约40,000个文档,每个文档中都包含大量数据)。
正在访问流:
var cursor = db.domains.find({ html: { $exists: true } });
cursor.on('data', function(rec) {
i++;
var url = rec.domain;
var $ = cheerio.load(rec.html);
checkList($, rec, url, i);
// This "checkList" function parses HTML data with Cheerio to find different elements on the page. Lots of if/else statements
});
cursor.on('end', function(){
console.log("Streamed all objects!");
})
每个记录都使用Cheerio
进行解析(记录包含之前抓取的页面中的HTML数据)然后我处理Cheerio数据以查找各种选择器,然后保存回MongoDB。
对于前〜2,000个对象,数据解析速度非常快(约30秒)。之后变得慢得多,每秒解析约50条记录。
查看我的Macbook Air的活动监视器,我发现它没有使用疯狂的内存量(226.5mb / 8gb ram),但是它使用了大量的CPU(io.js占据了我的cpu的99%)
这可能是内存泄漏吗? checkLists
函数不是特别密集(或者至少,据我所知 - 有很多嵌套if/else statements
,但没有其他的东西。
我是否打算在使用它们之后清除我的变量,比如设置$ = ''
或类似? Node的任何其他原因都会使用这么多CPU吗?
答案 0 :(得分:4)
你基本上需要"pause"流或其他"油门"它直接从收到的非常数据项上执行。所以"事件中的代码"除非你停止发射事件,否则在下一个事件被触发之前不会在完成之前等待。
var cursor = db.domains.find({ html: { $exists: true } });
cursor.on('data', function(rec) {
cursor.pause(); // stop processessing new events
i++;
var url = rec.domain;
var $ = cheerio.load(rec.html);
checkList($, rec, url, i);
// if checkList() is synchronous then here
cursor.resume(); // start events again
});
cursor.on('end', function(){
console.log("Streamed all objects!");
})
如果checkList()
包含异步方法,则传入光标
checkList($, rec, url, i,cursor);
处理"简历"内:
function checkList(data, rec, url, i, cursor) {
somethingAsync(args,function(err,result) {
// We're done
cursor.resume(); // start events again
})
}
"暂停"停止从流发出的事件,直到"恢复"叫做。这意味着您的操作不会叠加"在记忆中等待每一个完成。
对于某些并行处理,您可能需要更高级的流控制,但这基本上就是您使用流进行操作的方式。 内部恢复