为什么这个node.js循环在112050次迭代后运行缓慢?

时间:2013-01-27 23:47:41

标签: node.js performance loops file-io io

我正在玩node.js,我发现这个简单的程序运行速度非常慢,我甚至没有等到3分钟过后花了多长时间。

var fs = require ('fs')
var s = fs.createWriteStream("test.txt");
for (i = 1; i <= 1000000; i++)
      s.write(i+"\n");
s.end()

我尝试使用不同的值,发现虽然1-112050需要3秒,但1-112051需要一分钟。这种突然下降很奇怪。 python中的相同程序,或等效的shell脚本'seq 1 112051`在合理的时间内(0-2秒)运行。

请注意,此node.js应用程序的运行速度要快得多:

var fs = require('fs')
     , s = []
for (var i = 1; i <= 1000000; i++) s.push(i.toString())
s.push('')
fs.writeFile('UIDs.txt', s.join('\n'), 'utf8')

任何人都可以向我解释为什么node.js会这样做,以及为什么下降是如此突然?

3 个答案:

答案 0 :(得分:13)

这是因为for周期是同步的,但Writable.write()不是。对于您的示例,s.write会创建一百万 chuncks队列。这会导致超过一百万个函数调用(like this)来处理此队列。因此,Writable.write不适用于小块。您可check sources Writable.write获取有关它的更多信息。

答案 1 :(得分:6)

这是一个填满的缓冲区。每次写入都将返回truefalse,具体取决于内核缓冲区的状态。

如果您开始收听返回代码并使用drain事件,那么它的速度至少会一致。

var fs = require ('fs') 

function runTest(stop) {
  var s = fs.createWriteStream("test.txt");
  var startTime = Date.now();
  var c = 1;
  function doIt() {
    while (++c <= stop) {
      if (!s.write(c+"\n")) {
        s.once('drain', doIt);
        return;
      }
    }

    s.end();
    var diffTime = Date.now() - startTime;
    console.log(stop+': took '+diffTime+'ms, per write: '+(diffTime/stop)+'ms')
  }

  doIt();
}

runTest(10000);
runTest(100000);
runTest(1000000);
runTest(10000000);
runTest(100000000);

输出:

$ node test.js
10000: took 717ms, per write: 0.0717ms
100000: took 5818ms, per write: 0.05818ms
1000000: took 42902ms, per write: 0.042902ms
10000000: took 331583ms, per write: 0.0331583ms
100000000: took 2542195ms, per write: 0.02542195ms

答案 2 :(得分:-4)

我认为这可能是特定于环境的,你在什么情况下对此进行编码? 例如,最初我认为这是一个网站,但它涉及写文件,这让我失望。

否则,使用文件系统根据实现工作很有趣,我不是一个责怪编程语言,但我真的不知道javascript如何处理特定系统上的文件IO,文件IO中的性能是其中的科学自己的权利,可能与计算机科学本身一样古老。