使用Node.js写入磁盘会随着时间的推移而变慢

时间:2014-10-14 07:44:26

标签: javascript node.js io disk file-writing

我正在尝试使用Node.js将大文件(500 MByte)写入磁盘。我发现虽然前几个文件是在几秒钟内(通常是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

如果我使用更大的文件(两倍大,即1 GByte)运行相同的测试,则需要大约一半的时间才能写入变慢。

更新

我已经更改了我的Node.js应用程序,将所有内容写入单个文件,该文件会依次添加...现在服务器上显示如下:

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的使用应确保操作系统真正将所有内容写入磁盘。

更新2

我最初使用Node.js 0.10.32进行了测试。一旦我切换到0.11.13,效果就不会完全消失,但是它需要方式更多的时间才能发生。在原始设置中,问题出现在大约10个周期,Node.js为0.11.13,它最早发生在第30周期。

知道什么可能导致这种行为吗?

1 个答案:

答案 0 :(得分:3)

我前段时间遇到过类似的问题。最多可以进行并发I / O操作,因此Node将尽可能同时开始写入尽可能多的文件,其余的将排队,直到插槽空闲为止。

file 1 |-----------------------------------|
file 2  |-----------------------------------|
file 3   |-----------------------------------|
file 4                                      |-------------------------------------|

上面只是一个例子,但它显示了原理,在这种情况下写4个文件所需的时间比只写3个文件的时间长两倍。