Самый быстрый способ передачи сообщений между процессами в Linux?

Какая самая быстрая технология для отправки сообщений между процессами приложений C++ в Linux? Я смутно осознаю, что на столе лежат следующие техники:

  • TCP
  • UDP
  • Розетки
  • Трубы
  • Именованные каналы
  • Файлы с отображением памяти

есть ли еще способы и какой самый быстрый?


person user997112    schedule 08.01.2013    source источник
comment
Каковы требования к задержке для вашего приложения?   -  person paddy    schedule 09.01.2013
comment
@paddy в основном я буду стараться сбрить каждую нано/микросекунду, которую смогу.   -  person user997112    schedule 09.01.2013


Ответы (7)


Я бы посоветовал также посмотреть на это: Как использовать общую память с Linux в C.

По сути, я бы отказался от сетевых протоколов, таких как TCP и UDP, при выполнении IPC на одной машине. Они имеют накладные расходы на пакеты и привязаны к еще большему количеству ресурсов (например, порты, петлевой интерфейс).

person Sam    schedule 08.01.2013
comment
Связанный документ потрясающий! Спасибо - person Davide Berra; 08.12.2016

Хотя все приведенные выше ответы очень хороши, я думаю, нам придется обсудить, что является «самым быстрым» [и должно ли оно быть «самым быстрым» или просто «достаточно быстрым для»?]

Для БОЛЬШИХ сообщений разделяемая память, без сомнения, является очень хорошей техникой и очень полезной во многих отношениях.

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

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

С другой стороны, общая память полагается на какой-то другой механизм, чтобы сообщить другому потоку, что «у вас есть пакет данных для обработки». Да, это очень быстро, если у вас есть БОЛЬШИЕ пакеты данных для копирования, но я был бы удивлен, если бы на самом деле была огромная разница с каналом. Основное преимущество заключается в том, что другой стороне не нужно копировать данные из общей памяти, но она также зависит от наличия достаточной памяти для хранения всех сообщений «в полете» или от отправителя, имеющего возможность удерживать данные. .

Я не говорю «не используйте разделяемую память», я просто говорю, что не существует такого понятия, как «одно решение, которое лучше всего решает все проблемы».

Чтобы уточнить: я бы начал с реализации простого метода с использованием канала или именованного канала [в зависимости от того, что подходит для целей] и измерил его производительность. Если значительное время тратится на копирование данных, я бы рассмотрел возможность использования других методов.

Конечно, еще одним соображением должно быть «собираемся ли мы когда-нибудь использовать две отдельные машины [или две виртуальные машины в одной системе] для решения этой проблемы. В этом случае лучше выбрать сетевое решение, даже если оно не САМОЕ быстрое». , я запустил локальный стек TCP на своих машинах на работе для тестов и получил около 20-30 Гбит / с (2-3 ГБ / с) с устойчивым трафиком.Необработанный memcpy в том же процессе дает около 50-100 ГБит / с (5-10 ГБ/с) (если только размер блока ДЕЙСТВИТЕЛЬНО крошечный и не помещается в кеш L1). Я не измерял стандартный канал, но ожидаю, что это где-то примерно посередине этих двух чисел. [Это цифры которые подходят для ряда различных довольно современных ПК среднего размера - очевидно, на ARM, MIPS или другом встроенном контроллере ожидайте меньшего числа для всех этих методов]

person Mats Petersson    schedule 08.01.2013
comment
Мои сообщения будут небольшого размера. Однако я бы не хотел блокировать отправителя, если получатель не может скопировать. Это связано с тем, что представьте, что я отправляю данные о погоде в той же стране — самое последнее сообщение с данными о погоде переопределит любые оставшиеся сообщения, которые все еще обрабатываются в данный момент. Однако мне нравится тот факт, что вы говорите, что получатель будет автоматически уведомлен! - person user997112; 09.01.2013
comment
Есть разные способы сделать это. И может быть проще дать получателю взглянуть (кратко) на прочитанное сообщение и сказать: «Ну, оно старое, поэтому я просто выкину это», чем исправлять систему обмена сообщениями, чтобы разобраться во всем. Это предполагает, что ваша обработка на принимающей стороне значительна, и отправить данные относительно легко. Другой способ решить эту проблему — использовать двустороннюю систему, в которой получатель говорит, что я закончил, пожалуйста, отправьте следующий пакет сейчас!, а отправитель просто поддерживает его в актуальном состоянии в любой момент времени. - person Mats Petersson; 09.01.2013
comment
Хотя я согласен со всем этим, это будет зависеть от того, как используется разделяемая память. Например. можно реализовать двойную буферизацию: отправитель непрерывно выгружает данные в блок A, каждый раз блокируя блокировку и устанавливая «флаг доступности». После этого считыватели могут дождаться этой блокировки, повернуть буферы и сбросить этот флаг, чтобы они могли безопасно использовать самые последние данные (только для чтения) без копирования, в то время как записывающее устройство продолжает записывать в блок B. должен быть заблокирован другим замком или нет, может быть определено в зависимости от типа обработки данных, которую он выполняет. - person Sam; 09.01.2013
comment
Я согласен. В своем ответе я хотел объяснить, что есть несколько способов решить одну и ту же проблему, и все зависит от того, чего вы на самом деле пытаетесь достичь, что лучше, а не прямо заявлять, что одно решение лучше всего, потому что я не верю это верно. Если только данные не являются достаточно большими или обработка не очень тривиальна, фактический метод передачи данных, ВОЗМОЖНО, не является самым большим камнем преткновения. - person Mats Petersson; 09.01.2013
comment
Думаю, мы полностью согласны с тем, что ОП должен показать нам некоторые детали. - person Sam; 09.01.2013
comment
Это просто случай, когда сообщение отправляется получателю, получатель начинает обрабатывать данные, а затем, когда получатель заканчивает, начинает обрабатывать следующий фрагмент данных в очереди. Итак, я реализую систему очередей, отправитель отправляет данные получателю, используя любой метод, рекомендованный здесь. Помогло ли это предоставить больше информации? - person user997112; 09.01.2013
comment
Да, поэтому у меня есть следующие вопросы: Насколько велики эти части? Все части должны быть обработаны полностью и по порядку? - person Sam; 09.01.2013

Исследовательская группа NetOS Systems Research из Кембриджского университета, Великобритания, провела несколько тестов IPC (с открытым исходным кодом).

Исходный код находится по адресу https://github.com/avsm/ipc-bench .

Страница проекта: http://www.cl.cam.ac.uk/research/srg/netos/projects/ipc-bench/ .

Результаты: http://www.cl.cam.ac.uk/research/srg/netos/projects/ipc-bench/results.html

Это исследование было опубликовано с использованием приведенных выше результатов: http://anil.recoil.org/papers/drafts/2012-usenix-ipc-draft1.pdf

person DejanLekic    schedule 06.11.2015

Проверьте CMA и kdbus: https://lwn.net/Articles/466304/

Я думаю, что самые быстрые вещи в наши дни основаны на AIO. http://www.kegel.com/c10k.html

person Alex    schedule 08.01.2013
comment
AIO — это не самое быстрое решение для обмена данными между процессами на одном процессоре. Ваша вторая ссылка на самом деле не то, что я бы рекомендовал. - person James Kanze; 09.01.2013
comment
@JamesKanze, не могли бы вы уточнить свои моменты? Что касается c10k, я часто разделял вашу точку зрения, но я видел, что этот URL много раз цитировался на SO ?? - person user997112; 09.01.2013
comment
@user997112 user997112 Для чего-либо на одном процессоре общая память превосходит альтернативы безоговорочно. Между процессорами разница во времени между асинхронным вводом-выводом и использованием отдельных потоков незначительна, а многопоточная модель значительно чище и проще в разработке и обслуживании. При эффективной многопоточности я бы ни за что не выбрал асинхронный ввод-вывод. - person James Kanze; 09.01.2013
comment
Люди в основном комментировали размер сообщения, которым обмениваются, и используете ли вы один или два процессора. Но я считаю, что актуальным и важным вопросом является скорость событий. Если вы обрабатываете очень большое количество событий в секунду (скажем, сотни тысяч), AIO может дать вам преимущество. - person Alex; 09.01.2013
comment
@JamesKanze, а многопоточная модель значительно чище и проще в разработке и обслуживании. Я думал, что непредсказуемое упреждение было недостатком многопоточной модели, поэтому легче рассуждать о неблокирующих решениях ввода-вывода.... - person lucid_dreamer; 27.02.2019

Поскольку вы пометили этот вопрос как C++, я бы рекомендовал Boost.Interprocess:

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

Источник

Одно предостережение, которое я обнаружил, — это ограничения переносимости примитивов синхронизации. . Например, ни в OS X, ни в Windows нет собственной реализации для переменных условий межпроцессного взаимодействия, и поэтому они эмулируют их с помощью спин-блокировок.

Теперь, если вы используете *nix, который поддерживает общие примитивы процесса POSIX, проблем не будет.

Общая память с синхронизацией — хороший подход, когда речь идет о значительных объемах данных.

person pepper_chico    schedule 09.01.2013
comment
К сожалению, Boost раздут. - person étale-cohomology; 26.07.2020

Ну, вы могли бы просто иметь разделяемый сегмент памяти между вашими процессами, используя линукс общая память, также известная как SHM.

Он довольно прост в использовании, посмотрите на ссылку для некоторых примеров.

person cmc    schedule 08.01.2013

очереди сообщений posix работают довольно быстро, но имеют некоторые ограничения.

person arash kordi    schedule 28.07.2013