Javascript NodeJS-使用MongoJS流进行内存/CPU管理

Javascript NodeJS-使用MongoJS流进行内存/CPU管理,javascript,node.js,mongodb,cpu-usage,Javascript,Node.js,Mongodb,Cpu Usage,我正在解析来自MongoDB的一个相当大的数据集(大约有40000个文档,每个文档中都有相当数量的数据) 正在访问流,如下所示: var cursor = db.domains.find({ html: { $exists: true } }); cursor.on('data', function(rec) { i++; var url = rec.domain; var $ = cheerio.load(rec.html); chec

我正在解析来自MongoDB的一个相当大的数据集(大约有40000个文档,每个文档中都有相当数量的数据)

正在访问流,如下所示:

  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

对于前2000个对象,数据解析速度相当快(约30秒)。在这之后,它会变得慢得多,每秒解析大约50条记录

查看我的Macbook Air的活动监视器,我发现它并没有占用大量内存(226.5mb/8gb ram),但它占用了大量CPU(io.js占用了我99%的CPU)

这可能是内存泄漏吗?
checklist
函数不是特别密集(或者至少,据我所知,有很多嵌套的
if/else语句,但没有太多其他语句)

我是否打算在使用变量后清除它们,比如设置
$=''
或类似设置?节点的其他原因是否会占用如此多的CPU?

您基本上需要控制流,否则就不能在直接接收到的每个数据项上执行它。因此,“事件”中的代码不会在触发下一个事件之前等待完成,除非您停止事件的发出

  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);
并在内部处理“简历”:

“暂停”停止从流发出的事件,直到调用“恢复”。这意味着您的操作不会在内存中“堆叠”,而是等待每个操作完成

对于某些并行处理,您可能需要更高级的流控制,但这基本上就是您处理流的方式。 然后在内部继续

您基本上需要阻止流在直接接收到的每个数据项上执行。因此,“事件”中的代码不会在触发下一个事件之前等待完成,除非您停止事件的发出

  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);
并在内部处理“简历”:

“暂停”停止从流发出的事件,直到调用“恢复”。这意味着您的操作不会在内存中“堆叠”,而是等待每个操作完成

对于某些并行处理,您可能需要更高级的流控制,但这基本上就是您处理流的方式。
然后在内部继续

那么“游标”结果将被转换为流,但是您的“解析”结果很容易保留在内存中。但主要查看
流。暂停
,因为处理流不会用“on data”来“stop”。所以你只需要堆叠操作,比如垃圾收集和bson解析。使用剖析器!节点检查器是一个很好的开始“游标”结果转换成流的地方,但是“解析”结果很容易留在内存中。但主要查看
流。暂停
,因为处理流不会用“on data”来“stop”。所以你只需要堆叠操作,比如垃圾收集和bson解析。使用剖析器!node inspector是startWow的好地方,这太棒了,我一直在努力寻找这种代码优化的东西,这看起来正是我想要的。我将测试并报告。试一试,当我将记录发送到
checkList()
后重新启动游标时,它没有任何效果,但是当我将
cursor.restart()
放在我的
mongo.save()
函数的回调中时,它已经变得越来越快了!将需要研究并行处理,看看我可以从这里改进什么。干杯,伙计。@Jascination这基本上就是我说的,把“简历”放在包含的任何异步baccllback响应中。这是你想要等待的。您可能会在gere中获得更多的改进。看看迭代器的不同用法,你可以同时进行多个操作。哇,这太神奇了,我一直在努力寻找这种代码优化的东西,这看起来正是我想要的。我将测试并报告。试一试,当我将记录发送到
checkList()
后重新启动游标时,它没有任何效果,但是当我将
cursor.restart()
放在我的
mongo.save()
函数的回调中时,它已经变得越来越快了!将需要研究并行处理,看看我可以从这里改进什么。干杯,伙计。@Jascination这基本上就是我说的,把“简历”放在包含的任何异步baccllback响应中。这是你想要等待的。您可能会在gere中获得更多的改进。请看一下迭代器的不同用法,其中可以同时执行多个操作。