Производительность sendto () для многоадресной рассылки в Linux снижается у локальных слушателей - PullRequest
4 голосов
/ 29 июля 2011

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

Недавно мы заметили интересное явление: время выполнения sendto () увеличивается пропорционально количеству слушателей на машине.

Например, скажем, без слушателей базовое время для нашего вызова sendto () составляет 5 микросекунд. Каждый дополнительный слушатель увеличивает время вызова sendto () примерно на 2 микросекунды. Итак, если у нас есть 10 слушателей, теперь вызов sendto () занимает 2 * 10 + 5 = 25 микросекунд.

Это говорит о том, что вызов sendto () блокируется до тех пор, пока данные не будут скопированы для каждого слушателя.

Анализ стороны прослушивания также подтверждает это. Если имеется 10 слушателей, каждый слушатель получает данные на две микросекунды позже, чем предыдущий. (То есть первый слушатель получает данные примерно за пять микросекунд, а последний слушатель получает данные примерно за 23-25 ​​микросекунд.)

Есть ли способ, на программном или системном уровне, изменить это поведение? Что-то вроде неблокирующего / асинхронного вызова sendto ()? Или, по крайней мере, блокировать только до тех пор, пока сообщение не будет скопировано в память ядра, чтобы оно могло вернуться, не ожидая всех слушателей)?

Ответы [ 2 ]

0 голосов
/ 29 июля 2011

Многоадресный цикл невероятно неэффективен и не должен использоваться для высокопроизводительных сообщений. Как вы заметили, при каждой отправке ядро ​​копирует сообщение каждому локальному слушателю.

Рекомендуемый подход заключается в использовании отдельного метода IPC для распределения по другим потокам и процессам на одном хосте, совместно используемой памяти или сокетах Unix.

Например, это легко реализовать с помощью сокетов ZeroMQ, добавив соединение IPC над многоадресным соединением PGM в том же сокете ZeroMQ.

0 голосов
/ 29 июля 2011

Извините за вопрос очевидного, но неблокируется ли сокет? (добавьте O_NONBLOCK к набору флагов для порта - см. fcntl)

...