大きなCSVファイルを読み込んで解析しようとしていましたが、行ごとに非同期計算をいくつか行い、だから、私はPromise p
を作り、多くの.then(xxx)
を連鎖しようとし、csvの最後には.then(yyy)
という最後のカウントを出力する。約束の中のいくつかのものが実行されていません
ただし、この数値は加算されません。しかし、私がp = p.then(xxx)
とp = p.then(yyy)
を行うと、その数は(より小さいcsvファイルの場合)加算されますが、(大容量のcsvファイルの場合)時にはメモリリークに直面します。
私が間違っていたことはありますか?
var fs = require('fs')
const csv = require('fast-csv');
var Promise = require('bluebird')
var count = 0;
var actual = 0;
let p = Promise.resolve();
const stream = fs.createReadStream(`/Users/ssmlee/Desktop/KingKong_Sims_5M.txt`);
const csvStream = csv({
delimiter: ';'
})
.on('data', (row) => {
count++
if (count % 10000 === 0) {
console.log(count)
console.log(process.memoryUsage().heapUsed)
}
p.then(() => { // instead if we do p = p.then(() => it will work correctly
return Promise.resolve().delay(5)
.then(function() {
actual++
})
});
})
.on('end',() => {
p.then(() => { // instead if we do p = p.then(() => it will work correctly
console.log(actual); // 4999977 or something like this
console.log(count); // 5000000
});
});
stream.pipe(csvStream);
なぜ、動作するスキームがメモリをリークすると思いますか? 'p = p.then(...)'には何も問題ありません。その構造自体は、メモリリークを引き起こしません。 – jfriend00
私は 'process.memoryUsage()。heapUsed'を使ってメモリ使用量をチェックしています。メモリはガベージコレクションされていません。おそらく5m行のランダムなファイルを生成して、これが起こっているのを知ることができます –
これを実装する方法が選択されているため、大量のメモリを使用しています。あなたは、何十万という約束を同時に飛行させるのではなく、物事を適切に順序づけることによって、より少ない記憶を使うことができます。たとえば、最初の行を読み込み、CSVストリームを一時停止し、非同期操作を行い、CSVストリームの解放が完了すると、エンドツーエンドのタイミングを速めるためにいくつかの操作を並行して実行したいが、妥当なメモリー使用量が必要な場合は、50万ではなく、一度に(おそらく10個の)操作を並列に保つ必要があります。 – jfriend00