2015-06-30 2 views
21

Я сравниваю 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.

+0

@mscdex цикл while не помог, так как Node.js не сможет завершить текущий тик, а также не сможет обрабатывать очереди событий ввода-вывода ... приложение замерзнет. –

+0

Я верю в этом случае, очень важно исследовать также код Java. Ссылка на java-код, который вы указали в разделе 'P.S.', не работает. Не могли бы вы его обновить? –

+0

Эй, @JanOsch, спасибо, что заметили это. Я случайно удалил его из своей учетной записи. Вы можете проверить его сейчас; он снова в сети. –

ответ

1

Этот тест является ошибочным. UDP не гарантирует доставку чего-либо и не гарантирует, что он допустит ошибку в случае ошибки.

Ваше приложение может отправлять 1000 тыс. Дейтаграмм в 1 ГБ/с из приложения Java, но 90% датаграмм никогда не доходило до адресата ... назначение может даже не работать.

Если вы хотите провести любое тестирование UDP, вам понадобятся два приложения: по одному на каждом конце. Отправьте нумерованные датаграммы 1, 2, 3 ... и проверьте, что отправлено и что получено. Обратите внимание, что UDP не гарантирует упорядочения сообщений.

Ядра управляют локальной сетью по специальному пути. Есть огромные буферы, предназначенные для него, и более высокие пределы, ни один трафик никогда не проходит через сетевые карты или драйверы. Это очень отличается от отправки пакетов для реального.

Тесты могут показаться несколько хорошими, если они сделаны только на локальном хосте. Ожидайте, что все будет терпеть неудачу, когда оно будет проходить через любую физическую инфраструктуру.

PC1 <-----> switch <-----> PC2 

Предположим, что в одной комнате есть два компьютера, соединенных переключателем. Было бы небезопасно достигать 10k/s UDP-дейтаграмм на этой простой настройке, не теряя сообщений в случайном порядке.

И это всего лишь два компьютера в одной комнате. Это может быть намного хуже в Интернете и на большом расстоянии.

+3

Вам здесь не хватает. Я хорошо знаю, как работает UDP, и я не заинтересован в том, что получающая сторона может обрабатывать дейтаграммы, а также если сетевое соединение сможет передавать их без потерь; поэтому я прямо сказал, что датаграммы отправляются на какой-то неиспользуемый локальный порт. Это обсуждение связано с тем, сколько дейтаграмм в секунду приложений может запускаться при одинаковых внешних условиях (то есть в том же аппаратном обеспечении, в той же операционной системе и т. Д.). –

Смежные вопросы