为什么nodejs写入流会导致内存消耗增加?
问题描述:
我正在读取NodeJS中的45Mb文本文件,并对其上的每个字符进行一些处理。为什么nodejs写入流会导致内存消耗增加?
我的脚本的第一个版本从原始文件中取出一个字符,将它存储在一个累加器变量(result + = char)中,然后将结果保存在文本文件中。这是行不通的,因为文件太大了我在RAM上放了太多的数据,所以我得到一个错误:Javascript堆内存不足。我决定用写流这样我就可以在时间数据直接写入到磁盘上一个聊天所以这可以解决该问题:
fs = require('fs');
var proportion = 2;
var c = '';
fs.readFile('./concat/all.txt', 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
var h = parseInt(Math.sqrt(data.length/proportion));
var w = parseInt(h * proportion);
console.log(w, h);
var wstream = fs.createWriteStream('output.txt');
var lineCount = 0;
for(var x = 0; x < data.length; x++) {
if(data.charCodeAt(x) === 32 && x > 0 && data.charCodeAt(x - 1) === 32)
continue;
if(data.charCodeAt(x) === 10 && x > 0 && data.charCodeAt(x - 1) === 10)
continue;
c = (data.charCodeAt(x) === 10 || data.charCodeAt(x) === 13 || data.charCodeAt(x) === 9) ? " " : data.charAt(x);
lineCount++;
if(lineCount > w) {
c += "\n";
lineCount = 0;
}
wstream.write(c);
}
wstream.end();
});
但尽管如此,我发现了一个内存不足的错误。如果我评论wstream.write(c)
,剧本将毫无问题地运行。为什么?
答
流,流,流...
油门下的I/O:
流在块输入,暂停对于每个大块流,解析&操纵当前组块中的每个字符并将其写入输出。
然后,您可以恢复输入流以继续下一个输入流,直到完成。
我曾与节流使用createReadStream
& createWriteStream
这里是我猜是因为代码(有64MB
文件测试成功)
const fs = require('fs')
var w; var charCount = 0; var proportion = 2
//:This step was required to populate 'w'
fs.readFile('input.txt', 'utf8', function (err,data) {
if(err){return console.log(err)}
let h = parseInt(Math.sqrt(data.length/proportion))
w = parseInt(h * proportion); data = undefined;
console.log('[+] starting (w:',w,')'); EMX()
});
//:Here is the magick
function EMX(){
const I = fs.createReadStream('input.txt')
const O = fs.createWriteStream('output.txt')
I.on('end',()=>{console.log("[+] operation completed")})
I.on('data', (chunk) => {
I.pause(); let data = chunk.toString()
for(var x=0;x<data.length;x++){
if(data.charCodeAt(x) === 32 && x > 0 && data.charCodeAt(x - 1) === 32) continue
if(data.charCodeAt(x) === 10 && x > 0 && data.charCodeAt(x - 1) === 10) continue
c = (data.charCodeAt(x) === 10 || data.charCodeAt(x) === 13 || data.charCodeAt(x) === 9) ? " " : data.charAt(x)
if(charCount>w){c+="\n";charCount=0;} charCount++
O.write(c)
}
I.resume()
})
}
你的代码没有问题你for循环结束的也许1秒,写作仍然需要100秒。所以基本上它仍然在记忆中......你需要放慢你的'wstream.write(c);'调用。 –
...我甚至会说第一个字符只在退出readFile回调后才写入。并且在此之前,所有要写入的数据都会缓存在内存中。 –
那么?我的解决方案是**跨平台**,如你所愿? – EMX