2012-06-05 3 views
4

У меня есть сервер, который отправляет UDP-пакеты через многоадресную рассылку и несколько клиентов, которые перечисляют эти многоадресные пакеты. Каждый пакет имеет фиксированный размер 1040 байт, весь размер данных, который отправляется сервером, составляет 3 ГБ.Пакет UDP-пакетов по ядру linux

Моя среда следующим образом:

1 Гбит сети Ethernet

40 узлов, 1 Sender Node и 39 приемных узлов. Все узлы имеют одинаковую конфигурацию оборудования: 2 процессора AMD, каждый процессор имеет 2 ядра + 2,6 ГГц

На стороне клиента один поток считывает сокет и помещает данные в очередь. Один дополнительный поток выталкивает данные из очереди и выполняет небольшую обработку.

Во время передачи многоадресной передачи я признаю скорость передачи пакетов 30% на стороне узла. Наблюдая статистику netstat -su, я могу сказать, что недостающие пакеты клиентским приложением равны значению RcvbufErrors из вывода netstat.

Это означает, что все недостающие пакеты отбрасываются ОС, потому что буфер сокета заполнен, но я не понимаю, почему поток захвата не может прочитать буфер во времени. Во время передачи 2 из 4 сердечников используются на 75%, остальные спят. Я единственный, кто использует эти узлы, и я бы предположил, что у таких машин нет проблем с обработкой пропускной способности 1 Гбит. Я уже сделал некоторую оптимизацию, добавив флагов компилятора g ++ для amd cpus, это снизит скорость передачи пакетов до 10%, но по-прежнему слишком высока.

Конечно, я знаю, что UDP не является надежным, у меня есть собственный протокол коррекции.

У меня нет административных разрешений, поэтому мне не удается изменить системные параметры.

Любые подсказки, как я могу увеличить производительность?

EDIT: Я решил эту проблему, используя 2 потока, которые читают разъем. Буфер recv-сокета по-прежнему иногда заполняется. Но среднее падение составляет менее 1%, поэтому с ним не проблема.

+0

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

ответ

2

Помимо очевидного удаления всего несущественного из сокета чтения цикла:

  • Увеличение буфера приема сокета с setsockopt(2),
  • Использование recvmmsg(2), если ваше ядро ​​поддерживает его, чтобы уменьшить количество системных вызовов и копии ядро-пользовательские,
  • Рассмотрите возможность неблокирующего подхода с использованием краевого эффекта epoll(7),
  • Посмотрите, действительно ли вам нужны потоки, блокировка/синхронизация очень дорого.
+0

Только для полноты первой пули: (1) ядро ​​может ограничить размер - поэтому читайте на '/ proc/sys/net/core/rmem_max', & (2)' optval' для 'setsockopt' является' SO_RCVBUF' – nhed

-1

«На стороне клиента один поток считывает сокет и помещает данные в очередь». Я думаю, проблема в этой теме. Он не получает сообщений достаточно быстро. Слишком много времени тратится на что-то еще, например, на получение мьютекса при помещении данных в очередь. Попытайтесь оптимизировать операции в очереди, например, использовать незаблокированную очередь.

3

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

Я написал очень detailed blog post, поясняющий, как контролировать и настраивать каждый компонент. Трудно резюмировать в качестве краткого ответа здесь, поскольку существует так много разных компонентов, которые необходимо отслеживать и настраивать.

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