提问者:小点点

"JavaScript堆内存溢出"而流大文件


我正在尝试使用XML-

[30517:0x102801600]698057毫秒:标记扫描1408.2(1702.9)-

最后在JS stacktrace中:

致命错误:CALL_AND_RETRY_LAST分配失败-JavaScript堆内存溢出

我有一种感觉,我的内存正在耗尽,但增加允许的内存与--max-old-space-size(或其他)不工作时,文件是70GB,我只有16GB的RAM。

以下是我尝试做的代码:

var fs = require('fs'),
    path = require('path'),
    XmlStream = require('xml-stream'),
    MongoClient = require('mongodb').MongoClient,
    url = 'mongodb://username:password@my.server:27017/mydatabase',
    amount = 0;

MongoClient.connect(url, function(err, db) {

    var stream = fs.createReadStream(path.join(__dirname, 'motor.xml'));
    var xml = new XmlStream(stream);

    var docs = [];
    xml.collect('ns:Statistik');

    // This is your event for the element matches
    xml.on('endElement: ns:Statistik', function(item) {
        docs.push(item);           // collect to array for insertMany
        amount++;

        if ( amount % 1000 === 0 ) { 
          xml.pause();             // pause the stream events
          db.collection('vehicles').insertMany(docs, function(err, result) {
            if (err) throw err;
            docs = [];             // clear the array
            xml.resume();          // resume the stream events
          });
        }
    });

    // End stream handler - insert remaining and close connection
    xml.on("end",function() {
      if ( amount % 1000 !== 0 ) {
        db.collection('vehicles').insertMany(docs, function(err, result) {
          if (err) throw err;
          db.close();
        });
      } else {
        db.close();
      }
    });

});

我的问题是:我有内存泄漏吗?为什么Node允许代码像这样构建内存?除了为我的电脑购买70 GB内存之外,还有其他解决方案吗?


共1个答案

匿名用户

发布我的评论作为回答,因为它解决了问题,并且可能对其他难以以这种方式使用xml流的人有用。

有问题的是,Collection方法导致了这个问题,因为它迫使解析器在解析数组时收集已处理节点的所有实例。收集只能用于收集正在解析的每个节点的特定类型。默认行为是不这样做(由于解析器的流特性,可以让您轻松处理多千兆字节的文件)。

所以解决方案是删除这行代码,只使用endElement事件。