Я сравниваю Java UDP-клиент, который непрерывно отправляет дейтаграммы с полезной нагрузкой в 100 байт как можно быстрее. Он был реализован с использованием java.nio.*
. Тесты показывают, что он способен обеспечить постоянную пропускную способность 220 тыс. Дейтаграмм в секунду. Я не тестирую сервер; клиент просто отправляет дейтаграммы на какой-то неиспользуемый порт на localhost.UDP посылает производительность в Node.js
Я решил запустить тот же тест в Node.js, чтобы сравнить обе технологии, и было удивительно грустно видеть, что Node.js выполняется в 10 раз медленнее, чем Java. Позвольте мне провести вас через мой код.
Во-первых, создать UDP сокет с помощью Node.js-х dgram module:
var client = require('dgram').createSocket("udp4");
Затем я создаю функцию, которая посылает дейтаграмму с помощью этого сокета:
function sendOne() {
client.send(message, 0, message.length, SERVER_PORT, SERVER_ADDRESS, onSend);
}
Переменная message
представляет собой буфер , созданного из строки со ста символами при запуске приложения:
var message = new Buffer(/* string with 100 chars */);
Функция onSend
просто увеличивает переменную, которая содержит количество дейтаграмм, которые были отправлены до сих пор. Далее у меня есть функция, которая постоянно вызывает sendOne()
с помощью setImmediate()
:
function sendForever() {
sendOne();
setImmediate(sendForever);
}
Сначала я пытался использовать process.nextTick(sendForever)
, но я обнаружил, что она всегда ставит себя на вершине очереди событий, еще до событий ввода-вывода, как документы says:
Он запускается до любых дополнительных событий ввода-вывода (включая таймеры) в последующих тиках цикла событий.
Это предотвращает отправить IO события из когда-либо происходит, поскольку nextTick
постоянно помещает sendForever
на кончике очереди на каждом тике. Очередь растет с непрочитанными событиями ввода-вывода, пока он не делает Node.js аварии:
fish: Job 1, 'node client' terminated by signal SIGSEGV (Address boundary error)
С другой стороны, setImmediate
пожаров после ввода/вывода событий обратных вызовов, так вот почему я его использовать.
Я также создать таймер, который один раз в 1 секунду печатает на консоли сколько датаграммы были отправлены в последний второй:
setInterval(printStats, 1000);
И, наконец, я начинаю представляемого:
sendForever();
Бег на на той же машине, что и тесты Java, Node.js достигла устойчивой пропускной способности 21 тыс. дейтаграмм в секунду, в десять раз медленнее, чем Java.
Моя первая догадка поставить два sendOne
«S для каждого клеща, чтобы увидеть, если он будет в два раза пропускную способность:
function sendForever() {
send();
send(); // second send
setImmediate(sendForever);
}
Но это не изменило пропускную способность вообще.
У меня есть хранилище доступны на GitHub с полным кодом:
https://github.com/luciopaiva/udp-perf-js
Просто клонировать его на свой компьютер, cd
в папку и запустить:
node client
Я хочу, чтобы открыть обсуждение того, как этот тест может быть улучшен в Node.js, и если есть какой-то способ, мы можем увеличить пропускную способность Node.js. Есть идеи?
P.S .: для заинтересованных, вот Java part.
@mscdex цикл while не помог, так как Node.js не сможет завершить текущий тик, а также не сможет обрабатывать очереди событий ввода-вывода ... приложение замерзнет. –
Я верю в этом случае, очень важно исследовать также код Java. Ссылка на java-код, который вы указали в разделе 'P.S.', не работает. Не могли бы вы его обновить? –
Эй, @JanOsch, спасибо, что заметили это. Я случайно удалил его из своей учетной записи. Вы можете проверить его сейчас; он снова в сети. –