Подтвердить что ты не робот

Почему этот цикл node.js медленно запускается после 112050 итераций?

Я играл с 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 или эквивалентная оболочка script '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 ведет себя так, и почему падение настолько неожиданно?

4b9b3361

Ответ 1

Это буфер, который заполняется. Каждая запись возвращает true или false в зависимости от состояния буфера ядра.

Если вы начнете прослушивать код возврата и используете событие 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

Это происходит потому, что цикл for синхронный, но Writable.write() - нет. Для вашего примера s.write создает очередь один миллион chuncks. Это вызывает более чем один миллион вызовов функций (как это) для обработки этой очереди. Таким образом, Writable.write не предназначен для небольших кусков. Вы можете проверить источники Writable.write, чтобы получить дополнительную информацию об этом.

Ответ 3

Я считаю, что это может быть специфичным для среды, в каком контексте вы это кодируете? например, изначально я думал, что это для веб-сайта, но это связано с записью файлов, которые меня отбрасывают.

В противном случае работа с файловыми системами работает смешно в зависимости от реализаций, я не из тех, кто виноват в языках программирования, но я действительно не знаю, как javascript рассматривает файл IO на вашей конкретной системе, производительность в файле IO - это наука в ее собственного права, возможно, такого же старого, как сама компьютерная наука.