我正在尝试使用XML - > JSON - >我服务器上的MongoDB。我有一个NodeJS应用程序,它流式传输XML,将其转换为JSON,然后将其以1000个块的形式添加到MongoDB服务器。然而,在大约75000条记录之后,我的Macbook的风扇开始旋转得更快,处理速度非常慢。几分钟后,我收到了这个错误:
< ---最后几个GC --->
[30517:0x102801600] 698057 ms:标记扫描1408.2(1702.9) - > 1408.1(1667.4)MB,800.3 / 0.0 ms(自标记开始以0步开始+ 0.0 ms,最大步0.0 ms,标记开始803 ms后的最长时间)最后的手段 [30517:0x102801600] 698940 ms:标记扫描1408.1(1667.4) - > 1408.1(1667.4)MB,882.2 / 0.0 ms最后的手段
最后在JS stacktrace中:
致命错误:CALL_AND_RETRY_LAST分配失败 - JavaScript堆内存不足
我感觉我的内存不多了,但是当文件超过70 GB且我只有16 GB的内存时,用--max-old-space-size
(或其他)增加允许的内存不起作用。< / p>
以下是我要做的代码:
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的RAM之外,还有其他方法吗?
答案 0 :(得分:2)
将我的评论作为答案发布,因为它解决了这个问题,并且可能对以这种方式使用xml-stream
包进行难以实现的其他人有用。
问题是,collect
方法导致了问题,因为它强制解析器在解析时收集数组中已处理节点的所有实例。 collect
仅应用于从正在解析的每个节点收集特定类型的子项。默认行为是不这样做(由于解析器的流式特性允许您轻松处理多GB文件)。
因此解决方案是删除该行代码并使用endElement
事件。