Продуктивність IPC: названа труба проти сокета


114

Здається, всі кажуть, що названі труби швидші, ніж розетки IPC. Наскільки швидше вони? Я вважаю за краще використовувати розетки, оскільки вони можуть робити двосторонній зв'язок і дуже гнучкі, але вибирають швидкість над гнучкістю, якщо це буде значна сума.


10
Ваш пробіг буде відрізнятися. :) Профіль, типовий для використання за призначенням, і обирайте краще з двох. Потім профіліруйте анонімні канали, розетки інших доменів та сімей, семафори та спільну пам'ять чи черги повідомлень (SysV та POSIX), сигнали в реальному часі зі словом даних або будь-яким іншим. pipe(2)(er mkfifo(3),?) може бути переможцем, але ви не знаєте, поки не спробуєте.
pilcrow

2
Черги повідомлень SysV FTW! Я поняття не маю, якщо вони швидкі, у мене просто м'яке місце для них.
Том Андерсон

4
Що таке "швидкість" у цьому випадку? Загальна швидкість передачі даних? Або затримка (як швидко перший байт потрапить до приймача)? Якщо ви хочете швидкої локальної передачі даних, важко перемогти спільну пам'ять. Якщо ж затримка - це проблема, то питання стає цікавішим ...
Ян Ні-Льюїс

Відповіді:


64

Я б запропонував вам спершу пройти легкий шлях, обережно виділивши механізм IPC, щоб ви могли переходити від сокета до труби, але я обов'язково спершу перейду з розеткою. Ви повинні бути впевнені, що ефективність IPC є проблемою перед попередньою оптимізацією.

І якщо ви потрапили в біду через швидкість IPC, я думаю, вам слід розглянути можливість переходу на спільну пам'ять, а не переходити до роботи.

Якщо ви хочете зробити кілька тестувань швидкості передачі, вам слід спробувати socat , що є дуже універсальною програмою, яка дозволяє створювати практично будь-який вид тунелю.


48

Найкращі результати ви отримаєте з рішенням спільної пам'яті .

Названі труби лише на 16% кращі, ніж розетки TCP .

Результати отримують із тестування IPC :

  • Система: Linux (Linux ubuntu 4.4.0 x86_64 i7-6700K 4.00GHz)
  • Повідомлення: 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

1
Дякуємо за детальний бенчмаркінг. Ви маєте на увазі "multiprocessing.Queue" з "Queue message"?
ovunccetin

1
Черга повідомлень - це системна черга повідомлень XSI ( man7.org/linux/man-pages/man0/sys_msg.h.0p.html )
chronoxor

34

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

Багато людей, які клянуться названими трубами, знаходять невелику економію (залежно від того, наскільки добре написано все інше), але закінчуються кодом, який витрачає більше часу на блокування відповіді IPC, ніж на корисну роботу. Звичайно, це допомагають неблокуючі схеми, але вони можуть бути складними. Витрачаючи роки, приводячи старий код у сучасну епоху, можу сказати, у більшості випадків, які я бачив, швидкість майже нульова.

Якщо ви дійсно думаєте, що розетки будуть гальмувати вас, тоді вийдіть за ворота, використовуючи спільну пам'ять, уважно ставлячись до того, як ви використовуєте блокування. Знову ж таки, у всій актуальності ви можете виявити невелику швидкість, але зауважте, що ви витрачаєте частину на неї, очікуючи блокування взаємного виключення. Я не збираюся виступати за подорож до пекла футекс (ну, вже не зовсім пекло у 2015 році, залежно від вашого досвіду).

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


2
можливо, в якийсь день у далекому утопічному майбутньому у нас з’явиться абсолютно нове, модульне, сучасне ядро, яке неявно пропонує всі (міжпроцесорні та інші) здібності, якими ми зараз ходимо над розбитим склом, щоб досягти ... але так ... можна мріяти
Gukki5

27

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


1
Що з Windows?
Pacerier

1
@Pacerier На жаль, ви не можете створити локальні сокети в Windows так само, як абстрактні простори імен в UNIX. Я виявив, що PF_UNIX-сокети значно швидші (> 10%), ніж більшість інших методів, описаних на цій сторінці.
EntangledLoops



11

Якщо вам не потрібна швидкість, розетки - це найпростіший шлях!

Якщо ви дивитесь на швидкість, найшвидшим рішенням є спільна пам'ять, а не названі труби.


8

Для двостороннього зв'язку з названими трубами:

  • Якщо у вас мало процесів, ви можете відкрити дві труби для двох напрямків (processA2ProcessB і processB2ProcessA)
  • Якщо у вас багато процесів, ви можете відкривати і виводити труби для кожного процесу (processAin, processAout, processBin, processBout, processCin, processCout тощо)
  • Або ви можете піти гібридно, як завжди :)

Названі труби досить прості у виконанні.

Наприклад, я реалізував проект на C із названими трубами, завдяки стандартній комунікації на основі вводу-виводу (fopen, fprintf, fscanf ...), це було так просто і чисто (якщо це також враховується).

Я навіть кодував їх Java (я серіалізував і надсилав об’єкти над ними!)

Названі труби мають один недолік:

  • вони не масштабуються на декількох комп'ютерах, як сокети, оскільки вони покладаються на файлову систему (припустимо, що спільна файлова система не є опцією)

8

Одна з проблем з розетками полягає в тому, що вони не мають способу промити буфер. Існує щось, що називається алгоритмом Nagle, який збирає всі дані та видаляє їх через 40 мс. Тож якщо це чуйність, а не пропускна здатність, вам може бути краще з трубою.

Ви можете відключити Nagle за допомогою параметра socket TCP_NODELAY, але тоді кінець читання ніколи не отримає двох коротких повідомлень за один виклик читання.

Отже, протестуйте це, я нічого не закінчила, і реалізувала на основі пам'яті відображені черги на основі мутексу pthread та семафору у спільній пам'яті, уникаючи безлічі викликів системи ядра (але сьогодні вони вже не дуже повільні).


3
"Так випробуй" <- слова, якими потрібно жити.
Koshinae

6

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

Ми не можемо сказати вам, що буде краще, але я дуже підозрюю, що це не має значення.

Розетки для домену Unix будуть робити майже все, що буде з сокетами tcp, але лише на локальній машині та з (можливо, трохи нижчими).

Якщо сокет Unix недостатньо швидкий і ви переносите багато даних, подумайте про використання спільної пам’яті між вашим клієнтом і сервером (що набагато складніше налаштувати).

У Unix і NT обидва мають "названі труби", але вони абсолютно різні за набором функцій.


1
Добре, якщо ви відкриєте 2 труби, тоді ви також отримаєте поведінку біді.
Pacerier

4

Можна використовувати полегшений розчин на зразок ZeroMQ [ zmq / 0mq ]. Це дуже простий у використанні і значно швидше, ніж розетки.


2
Можливо, вам сподобається, Аміт, наступний твір Мартіна СУСТРІКА - сумісний з POSIX nanomsg. У будь-якому разі, ласкаво просимо та насолоджуйтесь цим чудовим місцем та станьте його активною учасницею.
user3666197
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.