Несколько лет назад мы изучали этот конкретный вопрос для ситуации клиент / сервер, когда клиент и сервер работали на одной машине. В то время мы использовали сокеты (UDP), даже когда клиент и сервер находились на одной машине. Для нас «лучшим» оказалась общая память с именованными семафорами для ее синхронизации. В то время я в основном изучал каналы по сравнению с необработанной реализацией совместно используемой памяти. Я тестировал каналы с перекрывающимся вводом / выводом и с портами завершения ввода / вывода.
Я тестировал с большим разнообразием размеров данных. На нижнем уровне, где клиент и сервер отражали 1 байт назад и вперед, реализация первичной общей памяти была быстрее всего в 3 раза. Когда я пропустил 10000 байт назад и вперед, реализации канала и исходная реализация общей памяти были все примерно с той же скоростью. Я использовал 4K буферы, если я правильно помню с реализацией общей памяти.
Для всех размеров данных тест общей памяти проходил в 2-6 раз быстрее, чем при использовании сокетов (по сравнению с TCP).
Между реализациями конвейера перекрывающаяся версия ввода-вывода была быстрее, чем версия порта завершения ввода-вывода, примерно на 30% при передаче небольших объемов данных. Опять же, при больших порциях данных разница была минимальной.
Реализация канала была, конечно, гораздо менее сложной для кода. Но мы имели дело с несколькими небольшими порциями данных, передаваемых взад и вперед, поэтому стоило дополнительной сложности реализовать версию совместно используемой памяти с именованными семафорами.
Конечно, как было упомянуто, это было несколько лет назад, и вы не представляете, правильно ли я реализовал все различные тесты. Обратите внимание, что это было с одним клиентом. Окончательная реализация нашего взаимодействия с разделяемой памятью очень хорошо масштабируется для сотен запущенных «клиентов». Но я не знаю, лучше ли это в таком масштабе, чем конвейерная реализация.