在node.js中解析XML会导致极大的内存使用

时间:2014-10-23 11:50:59

标签: node.js xml-parsing

我编写了一个小的node.js应用程序,它遍历一个1.8GB的xml文件,并对不同的元素执行一些数据库操作。但是我遇到了记忆问题。

var fs        = require('fs')
  , path      = require('path')
  , XmlStream = require('xml-stream')
  , pg = require('pg')
  , conString = "postgres://user:pass@localhost:5432/db"
  , schema = 'public'
  ;

function storeInDB(data){
  pg.connect(conString, function(err, client, done) {
    if(err) {
      return console.error('error fetching client from pool', err);
    }

    var sql = 'INSERT INTO '+schema+'.table (field1, field2) VALUES ($1, $2) ';

    client.query(sql,data, function(err, result) {
      done();
      if(err) {
        return console.error('error running query', err);
      }
    });
   })
 }

 var stream = fs.createReadStream('../path/to/some_large.xml');
 var xml = new XmlStream(stream);

 // Find the certificate entry and do things with it.
 xml.on('endElement: certificate', function(item) {
    var data = [item.field1, item.field2, ......];

    storeInDB(data);
 });

虽然这可行,但它开始逐渐消耗更多RAM。在htop中,我看到记忆的稳定增长百分比;直到我使用完整的RAM并且SWAP文件启动。由于IO,这会导致相当大的延迟。这是400.000处理过的证书;该文件包含大约2.5密耳的证书。

有些东西在吃记忆,但我不知道是什么。随着内存的构建证明,XML流不应该将数据加载到内存中。但看起来处理的数据不会以某种方式从内存中刷新。

有没有办法每个x证书刷新内存?或者应用程序错误'?

1 个答案:

答案 0 :(得分:0)

你绑定的事件:

xml.on('endElement: certificate')

会一遍又一遍地快速触发,而无需等待DB的写入完成。更新storeInDB以调用它:

xml.pause() // Put this as the first line in storeInDB to prevent too many events

并将其放入查询回调中:

xml.resume(); // Resume parsing 
done();

如果正在进行超过5个查询等,您可以改进此选项以仅调用暂停和恢复事件,但您明白了。

也可能值得研究不使用pg模块的连接池,而是通过client.connect使用单个连接。