readstream.pipe(transformstream).pipe(writeStream) を実行しています。アプリケーションは readstream を使用してファイル システムから xml を読み取ります --> 変換ストリームを使用してさまざまなタグに基づいて何らかの操作を行います --> 別のファイル システムに書き込みます。
トランスフォーム ストリーム内の変換操作中。プッシュする前に文字列を操作する必要があるため、すべてのチャンクに対して buffer.toString() を実行しています。
myTransformStream._transform = function(chunk, encoding, done) {
var stringTobeManipulated = chunk.toString();
// perform changes on stringTobeManipulated and push it to writestream
}
xml のサイズは最大 3 MB で、最大 44 個のチャンクに分割されていることに気付きました。
与えられた問題に基づいて、v8 ヒープとシステムの両方でのメモリ消費に関する質問があります。
1) バッファが v8 メモリの外部に格納されていることを理解しています。_transform 関数で chunk.toString() を実行すると、v8 メモリ内に JavaScript 文字列オブジェクトが作成されますか? はいの場合、すべての参照を失った後にガベージコレクションされると想定しています。
2)バッファはシステムメモリの一部であるため、ガベージコレクションされていないと思いますが、そのメモリはいつ解放されますか?
3) すべてのチャンクを文字列に変換しているので、アプリケーションは変換ストリームの適切な使用例ですか?
EDITED:私は自分自身を明確に説明していないかもしれません. とにかく、jsonに変換する前に、xmlタグから名前空間を削除する方法を見つけようとしています。これが私が最終的に得たコードです。javascrtipt のメモ化を利用しました。より良い、またはよりメモリ効率の良い方法を見つけたら教えてください。actionhero.js フレームワークを使用しています
var action = {};
var xml2js = require('xml2js');
var fs = require('fs');
/////////////////////////////////////////////////////////////////////
// metadata
action.name = 'removeNamespace';
action.description = 'I will parse the article related xml and yield the result';
action.inputs = {
'required': [],
'optional': []
};
action.blockedConnectionTypes = [];
action.outputExample = {
articleHeading: 'heading',
articleBody: 'body'
};
/////////////////////////////////////////////////////////////////////
// functional
action.run = function(api, connection, next) {
var stream = require('stream');
var removeNamespace = new stream.Transform();
var util = require('util');
var output = fs.createWriteStream('output.xml');
removeNamespace._transform = function(chunk, encoding, done) {
removeNamespace._transform.brokenTag = removeNamespace._transform.brokenTag || false;
removeNamespace._transform.brokenString = removeNamespace._transform.brokenString || '';
var convertedString = chunk.toString().trim();
if (removeNamespace._transform.brokenTag === true){
convertedString = removeNamespace._transform.brokenString + convertedString ;
}
removeNamespace._transform.brokenTag = false;
removeNamespace._transform.brokenString = '' ;
if (convertedString.lastIndexOf('<') > convertedString.lastIndexOf('>') ){
removeNamespace._transform.brokenString =convertedString.substring(convertedString.lastIndexOf('<'),convertedString.length+1);
convertedString = convertedString.substring(0,convertedString.lastIndexOf('<')) ;
removeNamespace._transform.brokenTag = true ;
}
convertedString = convertedString.replace(/>\s+</g, '><')
.replace.replace(/<[A-Za-z]+:/gi, '<')
.replace(/<\/[A-Za-z]+:/gi, '</');
done(null, convertedString);
};
var Writable = stream.Writable;
function xmlInMemory(keyToXml, options) {
Writable.call(this, options);
this[keyToXml] = new Buffer('');
this._write = function(chunk, encoding, callback) {
chunk = (Buffer.isBuffer(chunk)) ? chunk : new Buffer(chunk, encoding);
this[keyToXml] = Buffer.concat([this[keyToXml], chunk]);
callback();
};
}
util.inherits(xmlInMemory, Writable);
var source = fs.createReadStream('path/to/your/xmlfile');
var target = new xmlInMemory('keyToXml');
source.pipe(removeNamespace).pipe(target);
target.on('finish', function() {
var parser = new xml2js.Parser();
connection.response.xml2js = target.keyToXml.toString();
next(connection, true);
parser.parseString(target.keyToXml.toString(), function(err, result) {
connection.response.xml2js = result;
next(connection, true);
});
});
};
/////////////////////////////////////////////////////////////////////
// exports
exports.action = action;