Производительность IPC: именованный канал против сокета - PullRequest
90 голосов
/ 06 августа 2009

Кажется, все говорят, что именованные каналы работают быстрее, чем сокеты IPC. Насколько быстрее они? Я бы предпочел использовать сокеты, потому что они могут выполнять двустороннюю связь и очень гибки, но выберут скорость вместо гибкости, если она значительная.

Ответы [ 10 ]

55 голосов
/ 06 августа 2009

Я бы посоветовал вам сначала пойти по простому пути, тщательно изолируя механизм ipc, чтобы вы могли переходить от сокета к каналу, но сначала я определенно остановлюсь на сокете. Вы должны быть уверены, что производительность IPC является проблемой до упреждающей оптимизации.

И если у вас возникли проблемы из-за скорости IPC, я думаю, вам следует подумать о переключении на общую память, а не на конвейер.

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

30 голосов
/ 07 августа 2009

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

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

Если вы действительно думаете, что сокеты будут замедлять вас, тогда выходите из шлюза, используя разделяемую память, внимательно следя за тем, как вы используете блокировки. Опять же, в действительности вы можете обнаружить небольшое ускорение, но обратите внимание, что вы тратите часть этого времени на ожидание взаимных исключающих блокировок. Я не собираюсь выступать за поездку в futex hell (ну, а не вполне ад в 2015 году, в зависимости от вашего опыта).

Фунт за фунт, сокеты (почти) всегда лучший путь для IPC пользовательского пространства под монолитным ядром ... и (обычно) самый простой для отладки и обслуживания.

26 голосов
/ 25 марта 2013

Как часто цифры говорят больше, чем чувства, вот некоторые данные: Труба против производительности сокетов Unix (opendmx.net) .

Этот тест показывает разницу в скорости труб на 12-15%.

26 голосов
/ 22 июля 2011

Имейте в виду, что сокеты не обязательно означают IP (и TCP или UDP). Вы также можете использовать сокеты UNIX (PF_UNIX), которые предлагают заметное улучшение производительности по сравнению с подключением к 127.0.0.1

15 голосов
/ 13 января 2019

Наилучшие результаты вы получите с Shared Memory решением.

Именованные каналы только на 16% лучше, чем TCP-сокеты .

Результаты получены с помощью IPC-теста :

  • Система: Linux (Linux Ubuntu 4.4.0 x86_64 i7-6700K 4,00 ГГц)
  • Сообщение: 128 байт
  • Количество сообщений: 1000000

Трубный эталон:

Message size:       128
Message count:      1000000
Total duration:     27367.454 ms
Average duration:   27.319 us
Minimum duration:   5.888 us
Maximum duration:   15763.712 us
Standard deviation: 26.664 us
Message rate:       36539 msg/s

Контрольный показатель FIFO (именованные трубы):

Message size:       128
Message count:      1000000
Total duration:     38100.093 ms
Average duration:   38.025 us
Minimum duration:   6.656 us
Maximum duration:   27415.040 us
Standard deviation: 91.614 us
Message rate:       26246 msg/s

Тест очереди сообщений:

Message size:       128
Message count:      1000000
Total duration:     14723.159 ms
Average duration:   14.675 us
Minimum duration:   3.840 us
Maximum duration:   17437.184 us
Standard deviation: 53.615 us
Message rate:       67920 msg/s

Тест общей памяти:

Message size:       128
Message count:      1000000
Total duration:     261.650 ms
Average duration:   0.238 us
Minimum duration:   0.000 us
Maximum duration:   10092.032 us
Standard deviation: 22.095 us
Message rate:       3821893 msg/s

Тест TCP-сокетов:

Message size:       128
Message count:      1000000
Total duration:     44477.257 ms
Average duration:   44.391 us
Minimum duration:   11.520 us
Maximum duration:   15863.296 us
Standard deviation: 44.905 us
Message rate:       22483 msg/s

Тест доменных сокетов Unix:

Message size:       128
Message count:      1000000
Total duration:     24579.846 ms
Average duration:   24.531 us
Minimum duration:   2.560 us
Maximum duration:   15932.928 us
Standard deviation: 37.854 us
Message rate:       40683 msg/s

Тест ZeroMQ:

Message size:       128
Message count:      1000000
Total duration:     64872.327 ms
Average duration:   64.808 us
Minimum duration:   23.552 us
Maximum duration:   16443.392 us
Standard deviation: 133.483 us
Message rate:       15414 msg/s
10 голосов
/ 23 декабря 2009

Если вам не нужна скорость, розетки - самый легкий путь!

Если вы смотрите на скорость, то самое быстрое решение - общая память, а не именованные каналы.

8 голосов
/ 20 июня 2015

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

Вы можете отключить Nagle с помощью опции сокета TCP_NODELAY, но тогда конец чтения никогда не получит два коротких сообщения за один вызов чтения.

Итак, протестируйте, я ничего не закончил и реализовал очереди на основе отображения памяти с мьютексом pthread и семафором в разделяемой памяти, избегая многих системных вызовов ядра (но сегодня они уже не очень медленные). *

8 голосов
/ 21 сентября 2010

Для двусторонней связи с именованными каналами:

  • Если у вас мало процессов, вы можете открыть два канала для двух направлений (processA2ProcessB и processB2ProcessA)
  • Если у вас много процессов, вы можете открывать и выводить каналы для каждого процесса (processAin, processAout, processBin, processBout, processCin, processCout и т.д.)
  • Или вы можете пойти гибридом, как всегда:)

Именованные каналы довольно легко реализовать.

например. Я реализовал проект в C с именованными каналами, благодаря стандартному обмену данными на основе ввода-вывода файлов (fopen, fprintf, fscanf ...), это было так просто и чисто (если это тоже соображение).

Я даже закодировал их с помощью Java (я сериализировал и отправлял объекты поверх них!)

Именованные каналы имеют один недостаток:

  • они не масштабируются на нескольких компьютерах, таких как сокеты, поскольку полагаются на файловую систему (при условии, что совместно используемая файловая система не является опцией)
6 голосов
/ 06 августа 2009

Именованные трубы и розетки не являются функционально эквивалентными; сокеты предоставляют больше возможностей (для начала они двунаправлены).

Мы не можем сказать вам, что будет лучше, но я сильно подозреваю, что это не имеет значения.

Доменные сокеты Unix будут делать то же, что и сокеты tcp, но только на локальном компьютере и с (возможно, немного) меньшими издержками.

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

Unix и NT оба имеют «Именованные каналы», но они полностью различаются по набору функций.

3 голосов
/ 02 апреля 2017

Вы можете использовать облегченное решение, например ZeroMQ [ zmq / 0mq ]. Он очень прост в использовании и значительно быстрее, чем розетки.

...