2017-08-06 606 views
0

我想在我的服务器上的XML - > JSON - > MongoDB。我有一个NodeJS应用程序,它将XML流转化为JSON,然后以1000个块的形式将其添加到MongoDB服务器。然而,在大约75000条记录之后,我的Macbook的粉丝开始快速旋转,并且处理速度非常慢。几分钟后,我得到这个错误:“JavaScript堆内存不足”,而流大文件

<--- Last few GCs --->

[30517:0x102801600] 698057 ms: Mark-sweep 1408.2 (1702.9) -> 1408.1 (1667.4) MB, 800.3/0.0 ms (+ 0.0 ms in 0 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 803 ms) last resort [30517:0x102801600] 698940 ms: Mark-sweep 1408.1 (1667.4) -> 1408.1 (1667.4) MB, 882.2/0.0 ms last resort

终于在JS堆栈跟踪:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

我有一种感觉,我的记忆已经不多了,但--max-old-space-size增加允许的内存(或什么)不起作用时,文件是70 +千兆字节,我只有16GB的RAM。

这里是什么,我试图做的代码:

var fs = require('fs'), 
    path = require('path'), 
    XmlStream = require('xml-stream'), 
    MongoClient = require('mongodb').MongoClient, 
    url = 'mongodb://username:[email protected]: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的RAM之外,是否还有修复程序?

+0

_“当文件为70+千兆字节时,我只有16GB的内存。”_预计的结果是什么?单个70GB文件的目的是什么?这不是一个完整的操作系统版本? – guest271314

+0

@ guest271314我的理论是,我添加到外部MongoDB的数据存储在我的机器上的内存中,因为它永远不会清除它(除非当我执行'docs = []'时)。 – MortenMoulder

+0

对node.js或mongodb不够熟悉以提供可验证的评估。乍一看,70GB文件很有趣。或者是问题1或多个包含文件的目录中提到的70GB总数据传输? – guest271314

回答

1

发表我的评论作为答案,因为它解决了这个问题,并且可能对其他人以这种方式使用xml-stream包有所帮助。

问题在于,collect方法引发了这个问题,因为它迫使解析器在数组解析时收集数组中已处理节点的所有实例。 collect应仅用于从正在分析的每个节点收集特定类型的子项目。默认行为不是这样做的(由于解析器的流式性质,可以轻松处理多GB字节文件)。

所以解决方法是删除该行代码,并使用endElement事件。