2017-08-06 75 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事件。