首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在大型集和回调上使用map()的Javascript内存消耗

在大型集和回调上使用map()的Javascript内存消耗
EN

Stack Overflow用户
提问于 2014-09-16 19:49:18
回答 2查看 230关注 0票数 0

我甚至不知道如何恰当地问这个问题,但我担心以下代码的性能(主要是内存消耗)。我预计这段代码将消耗大量内存,因为大量的map和许多等待外部服务的“挂起”函数。我的担忧在这里是合理的吗?什么是更好的方法?

代码语言:javascript
复制
var list = fs.readFileSync('./mailinglist.txt') // say 1.000.000 records
  .split("\n")
  .map( processEntry );

var processEntry = function _processEntry(i){
  i = i.split('\t');
  getEmailBody( function(emailBody, name){
      var msg = {
      "message" :  emailBody,
      "name" : i[0]
      }
      request(msg, function reqCb(err, result){
        ...
      });
  }); // getEmailBody
}

var getEmailBody = function _getEmailBody(obj, cb){
// read email template from file; 
// v() returns the correct form for person's name with web-based service
  v(obj.name, function(v){
    cb(obj, v)
  });
}
EN

回答 2

Stack Overflow用户

发布于 2014-09-16 20:37:26

如果您担心在很短的时间内提交一百万个http请求(您可能应该这样做),那么您必须设置某种类型的缓冲区。

一个简单的方法就是:

代码语言:javascript
复制
var lines = fs.readFileSync('./mailinglist.txt').split("\n");

var entryIdx = 0;
var done = false;

var processNextEntry = function () {
    if (entryIdx < lines.length) {
        processEntry(lines[entryIdx++]);
    } else {
        done = true;
    }
};

var processEntry = function _processEntry(i){
  i = i.split('\t');
  getEmailBody( function(emailBody, name){
      var msg = {
      "message" :  emailBody,
      "name" : name
      }
      request(msg, function reqCb(err, result){
        // ...
        !done && processNextEntry();
      });
  }); // getEmailBody
}

// getEmailBody didn't change

// you set the ball rolling by calling processNextEntry n times,
// where n is a sensible number of http requests to have pending at once.

for (var i=0; i<10; i++) processNextEntry();

编辑:根据this blog post节点有一个内部队列系统,它将只允许5个同时请求。但是,如果您担心内存消耗,您仍然可以使用此方法来避免用一百万个项目来填满内部队列。

票数 1
EN

Stack Overflow用户

发布于 2014-09-16 21:33:22

首先,我建议不要使用readFileSync,相反,我倾向于使用异步等效项。应该避免阻塞IO操作,因为从磁盘读取是非常昂贵的,虽然这是您现在代码的唯一目的,但我会考虑这种情况在未来可能会发生什么变化-随意浪费时钟周期从来都不是一个好主意。

对于大型数据文件,我会在定义的块中读取它们,并对其进行处理。如果您能想出一些模式,无论是用来区分文件中的数据块的标记,还是填充边界,然后逐段地处理文件。

这很粗糙,在我脑海中没有经过测试,但大概是这样的:

代码语言:javascript
复制
var fs = require("fs");

function doMyCoolWork(startByteIndex, endByteIndex){

    fs.open("path to your text file", 'r', function(status, fd) {

            var chunkSize = endByteIndex - startByteIndex;
            var buffer = new Buffer(chunkSize);

            fs.read(fd, buffer, 0, chunkSize, 0, function(err, byteCount) {

                var data = buffer.toString('utf-8', 0, byteCount);

                // process your data here


                if(stillWorkToDo){
                    //recurse
                    doMyCoolWork(endByteIndex, endByteIndex + 100);
                }
            });
        });
}

或者查看流程库函数中的一个,以获得类似的功能。

H2H

ps。Javascript和Node与异步和事件一起工作得非常好。在我看来,使用sync是一种反模式,并且很可能导致代码在未来成为一个令人头疼的问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25868015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档