Запись потока Node.js в цикле

В последнее время я пытался сравнить некоторые нативные функции node.js и обнаружил некоторые жуткие результаты, которые я не могу понять. Вот простой код, который я тестировал и тестировал результаты:

http://pastebin.com/0eeBGSV9

Вы можете видеть, что он выполнил 8553 запросов в секунду на 100 000 запросов с 200 параллелизмом. Затем мой друг сказал мне, что я не должен использовать асинхронность в этом случае, так как этот цикл недостаточно велик, чтобы препятствовать циклу обработки событий узла, поэтому я реорганизовал код для использования в цикле, и это даже увеличило результат теста выше:

http://pastebin.com/0jgRPNEC

Здесь у нас 9174 запросов в секунду. Ухоженная. (версия цикла была стабильно быстрее, чем асинхронная версия, даже когда я изменил количество итераций на 10 000, что довольно любопытно).

Но потом мой друг забрел, можно ли продвинуть этот результат еще дальше, используя потоковую передачу вместо выгрузки всех данных после завершения цикла. Еще раз, я реорганизовал код для использования res.write для обработки вывода данных:

http://pastebin.com/wM0x5nh9

аааа а у нас 2860 запросов в секунду. Что здесь случилось? Почему потоковая запись так вяло? Есть ли какая-то ошибка в моем коде или это то, как узел на самом деле работает с потоками?

Версия узла 0.10.25 на Ubuntu с настройками по умолчанию из apt установки.

Я также протестировал тот же код на JXCore и HHVM (используя версию кода узла async.js) вначале с результатами здесь: http://pastebin.com/6tuYGhYG и получил любопытный результат, когда кластер узлов работает быстрее, чем последний jxcore 2.3 0,2.

Любая критика будет принята с благодарностью.

РЕДАКТИРОВАТЬ: @Mscdex, мне было любопытно, если бы вызов res.write() мог быть проблемой, поэтому я изменил способ выталкивания данных в новый поток, созданный для потребления res. Я наивно полагал, что, возможно, таким образом узел каким-то образом оптимизирует буферизацию вывода и потоковую передачу данных эффективным способом. Хотя это решение тоже работало, оно было еще медленнее, чем раньше:

http://pastebin.com/erF6YKS5

1 ответ

Я думаю, что это связано с наличием множества отдельных write() Системные вызовы.

В узле v0.12+ была добавлена функция "укупорки" , чтобы вы могли res.write() столько, сколько вы хотите, но вы можете закупорить и открепить поток так, чтобы все эти записи приводили только к одному write() Системный вызов. Это, по сути, то, что вы делаете сейчас с конкатенацией выходных данных, за исключением того, что пробка сделает это за вас. В некоторых местах в ядре узла эта функция укупорки может также использоваться автоматически за кулисами, чтобы вам не пришлось явно пробовать / отжимать, чтобы получить хорошую производительность.

Другие вопросы по тегам