解析大量文件的Meteor / Node.js变得非常慢

时间:2016-07-26 16:35:39

标签: node.js csv meteor

我有大约1000个需要解析的CSV文件。每个包含大约1000行,总共100万条记录。需要转换数据然后保存到数据库,这就是我必须通过我的应用程序执行此操作的原因。

我的问题是解析器在循环遍历文件时会逐渐变慢,直到完成运行需要它。

以下是目前的设置方式。

var files = [ file1Path, file2Path.... file1000Path ];

function parseFile(index) {
  var startTime = new Date().getTime();
  var filePath = files[index];
  var stream = fs.createReadStream(filePath);

  //parse using fast-csv npm module
  csv.fromStream(stream, { config })
     .on('data', function (row) {
        transformAndSave(row);
     })
     .on('end', function () {
       console.log( new Date().getTime() - startTime + " elapsed " );
       parseFile(index + 1)
     });
}
parseFile(0);

我尝试了几种不同的方式,每次都基本相同。第一个文件在2秒内完成,第8个文件在5秒或6秒完成,之后在上升到24秒等等。我尝试过的其他事情包括做... files.forEach(function (file) { //run the parser }),做批次它一次只有100个,甚至一次只有5个,并没有区别:它逐渐从每秒500个速度减慢到每秒1个或2个。

有没有人知道如何防止这种减速?部分原因可能是stream.on('end')transformAndSave完成之前完成,可能会产生积压。但是在这一点上,我没有想法,并且会感谢任何人都可以提供的任何帮助。

提前多多感谢!!

丹尼尔

对于流星人来说,请注意。我把这个函数称为Meteor方法。不确定这是否有所不同,但如果确实如此,现在你知道了。

更新 这是日志输出,显示内存使用和处理时间的稳步上升。

Log output

1 个答案:

答案 0 :(得分:2)

看起来像资源问题,就像你的内存不足一样。我会尝试一种不使用递归函数的方法,该函数可能允许更容易地释放资源。一种方法可能是使用async

var Logger = require('arsenic-logger');
var fs = require('fs');
var async = require('async');
var csv = require('fast-csv');
var path = require('path');

Logger.echoMemoryUsage();

var testDir = path.resolve(__dirname, 'test');

fs.readdir(testDir, (err, files) => {

    Logger.debug(files);

    if (err) {
        Logger.error(err);
    }

    async.mapLimit(files, 2, function(file, cb) {

        var startTime = new Date().getTime();
        var stream = fs.createReadStream(testDir+'/'+file);

        Logger.debug("Reading: " + file);

        config = {};

        //parse using fast-csv npm module
        csv.fromStream(stream, config)
            .on('data', function(row) {
                //Logger.debug(row);
                //transformAndSave(row);
            })
            .on('error', function(err) {
                Logger.error(err);
                cb(err);
            })
            .on('end', function() {
                Logger.debug(new Date().getTime() - startTime + " elapsed ");
                setTimeout(cb, 1000);
            });

    }, function(err, results) {
        Logger.info("Finished!");
        process.exit(1);
    });

});