Node.js を使用して大きなファイル (500 MB) をディスクに書き込もうとしています。最初の数ファイルは数秒 (通常は 3 ~ 5 秒) で書き込まれますが、10 番目のファイルあたりから書き込みが遅くなる傾向がある (そして回復しない) ことがわかりました。
セットアップは、TCP/IP ソケットを介してファイルを受け取り、それらをディスクにパイプするサーバーで構成されます。
var fs = require('fs'),
net = require('net'),
path = require('path');
var counter = 0;
net.createServer(function (socket) {
console.time('received');
console.time('written');
counter++;
var filename = path.join(__dirname, 'temp' + counter + '.tmp');
var file = fs.createWriteStream(filename, { encoding: 'utf8' });
socket.pipe(file);
socket.once('end', function () {
console.timeEnd('written');
});
file.once('finish', function () {
console.timeEnd('received');
});
}).listen(3000);
nc
次の方法で端末からデータを送信します。
$ while [ true ]; do `cat input.tmp | nc localhost 3000`; done
ランニング
$ time cat input.tmp > /dev/null
cat は常に同じ時間でファイルを読み取ることが示されています。Node.js スクリプトの出力パス/dev/null
も書き込みに置き換えると、常に同じタイミングで発生します。
したがって、問題は明らかにディスクへの実際の書き込みに関連しています。
最初は同時読み取りと書き込みに問題があるのではないかと考えましたが、実行しても問題は解決しません
$ while [ true ]; do `cat input.tmp | nc localhost 3000; sleep 5`; done
さらに大きなファイル (2 倍、つまり 1 GB) で同じテストを実行すると、書き込みが遅くなるまでに約半分の時間がかかります。
アップデート
Node.js アプリケーションを変更して、すべてを 1つのファイルに書き込むようにしました。このファイルは何度も何度も追加されます。サーバーは次のようになります。
var fs = require('fs'),
net = require('net'),
path = require('path');
var filename = path.join(__dirname, 'temp.tmp');
var file = fs.createWriteStream(filename, { encoding: 'utf8' });
net.createServer(function (socket) {
console.time('received');
console.time('written');
socket.pipe(file, { end: false });
socket.once('end', function () {
console.timeEnd('written');
});
}).listen(3000);
これで問題はなくなったので、複数のファイルを連続して書き込むことに関係しているようです。少なくとも複数のファイルを同時に書き込んでいる場所が見当たらないので(私でしょうか?)、なぜこうなったのか理由が思い浮かびません。特に の使用でsleep 5
は、OS が実際にすべてをディスクに書き込んだことを確認する必要があります。
更新 2
私は最初に Node.js 0.10.32 を使用してテストしました。0.11.13 に切り替えるとすぐに、効果が完全になくなるわけではありませんが、発生するまでに時間がかかります。元のセットアップでは、問題は約 10 サイクルで発生しました。Node.js 0.11.13 では、30 サイクルで最も早く発生しました。
この動作の原因は何ですか?