самый быстрый (с низкой задержкой) способ межпроцессного взаимодействия между Java и C/C++



У меня есть Java-приложение, подключающееся через TCP-сокет к "серверу", разработанному на C/C++.



оба приложения и сервера работают на одной машине, поле Solaris (но мы рассматриваем возможность перехода на Linux в конечном итоге).
тип обмениваемых данных-это простые сообщения (логин, логин ACK, затем клиент что-то просит, сервер отвечает). каждое сообщение составляет около 300 байт.



В настоящее время мы используем сокеты, и все в порядке, однако я ищу более быстрый способ обмена данными (более низкая задержка), используя методы IPC.



Я исследовал сеть и придумал ссылки на следующие технологии:




  • общий

  • труб

  • очереди

  • а также то, что называется DMA (прямой доступ к памяти)


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



может ли кто-нибудь прокомментировать производительность и осуществимость каждого метода в этом контексте ?
любой указатель / ссылка на полезную информацию о реализации ?





РЕДАКТИРОВАТЬ / ОБНОВИТЬ



после комментария и ответов, которые я получил здесь, я нашел информацию о сокетах домена Unix, которые, похоже, построены только над трубами, и спасут меня от всего стека TCP.
это специфическая платформа, поэтому я планирую протестировать ее с помощью JNI или либо juds или junixsocket.



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





спасибо за помощь

900   10  

10 ответов:

только что протестирована задержка с Java на моем Corei5 2.8 GHz, только один байт отправки / получения, 2 Java-процессы только что появились, без назначения определенных ядер процессора с набором задач:

TCP         - 25 microseconds
Named pipes - 15 microseconds

теперь явно указывая основные маски, как taskset 1 java Srv или taskset 2 java Cli:

TCP, same cores:                      30 microseconds
TCP, explicit different cores:        22 microseconds
Named pipes, same core:               4-5 microseconds !!!!
Named pipes, taskset different cores: 7-8 microseconds !!!!

так

TCP overhead is visible
scheduling overhead (or core caches?) is also the culprit

в то же время нить.sleep(0) (который, как показывает strace, вызывает один вызов ядра Sched_yield () Linux) занимает 0,3 микросекунды-так называемые трубы, запланированные для одного ядра, все еще имеют много накладных расходов

некоторые измерения общей памяти: 14 сентября 2009 г. – Solace Systems объявила сегодня, что ее API платформы Единой системы обмена сообщениями может достичь средней задержки менее 700 наносекунд с использованием транспорта с общей памятью. http://solacesystems.com/news/fastest-ipc-messaging/

С. П. - попробовал общей памяти на следующий день в виде памяти файл карты, если занятое ожидание приемлемо, мы можем уменьшить задержку до 0,3 микросекунды для передачи одного байта с таким кодом:

MappedByteBuffer mem =
  new RandomAccessFile("/tmp/mapped.txt", "rw").getChannel()
  .map(FileChannel.MapMode.READ_WRITE, 0, 1);

while(true){
  while(mem.get(0)!=5) Thread.sleep(0); // waiting for client request
  mem.put(0, (byte)10); // sending the reply
}

Примечание: Резьбы.сон (0) необходим, чтобы 2 процесса могли видеть изменения друг друга (Я еще не знаю другого способа). Если 2 процесса принудительно к одному ядру с набором задач, задержка становится 1,5 микросекунды - это задержка переключения контекста

P. P. S - и 0,3 микросекунды-это хорошее число! Следующий код занимает ровно 0.1 микросекунды, при выполнении только примитивной конкатенации строк:

int j=123456789;
String ret = "my-record-key-" + j  + "-in-db";

P. P. P. S-Надеюсь, это не слишком много вне темы, но, наконец, я попытался заменить поток.sleep(0) с приращением статической изменчивой переменной int (JVM происходит для очистки кэшей процессора при этом) и полученная запись! - 72 наносекунд задержки java-to-java процесс связи!

при принудительном использовании одного и того же ядра процессора, однако, изменчивые приращения JVM никогда не дают контроля друг над другом, таким образом, производя ровно 10 миллисекундную задержку - Linux time quantum, кажется, составляет 5 мс... Поэтому это следует использовать только в том случае, если есть запасное ядро - в противном случае сон(0) безопаснее.

вопрос был задан некоторое время назад, но вы можете быть заинтересованы в https://github.com/peter-lawrey/Java-Chronicle который поддерживает типичные задержки 200 нс и пропускную способность 20 м сообщений в секунду. Он использует сопоставленные с памятью файлы, разделяемые между процессами (он также сохраняет данные, что делает его самым быстрым способом сохранения данных)

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

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

вот проект, содержащий тесты производительности для различных IPC-транспортов:

http://github.com/rigtorp/ipc-bench

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

поздний приезд, но хотел указать на проект с открытым исходным кодом предназначен для измерения задержки ping с помощью Java NIO.

дальнейшее изучение / объяснение в этом блоге. Результаты (RTT в nanos):

Implementation, Min,   50%,   90%,   99%,   99.9%, 99.99%,Max
IPC busy-spin,  89,    127,   168,   3326,  6501,  11555, 25131
UDP busy-spin,  4597,  5224,  5391,  5958,  8466,  10918, 18396
TCP busy-spin,  6244,  6784,  7475,  8697,  11070, 16791, 27265
TCP select-now, 8858,  9617,  9845,  12173, 13845, 19417, 26171
TCP block,      10696, 13103, 13299, 14428, 15629, 20373, 32149
TCP select,     13425, 15426, 15743, 18035, 20719, 24793, 37877

Это соответствует принятому ответу. Система.погрешность nanotime () (оцененная путем измерения ничего) измеряется примерно на 40 нанометров, поэтому для IPC фактический результат может быть ниже. Наслаждаться.

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

в моей бывшей компании мы работали с этим проектом, http://remotetea.sourceforge.net/, очень легко понять и интегрировать.

вы рассматривали держать гнезда открытым, поэтому соединения можно повторно использовать?

отчет об ошибке Oracle по производительности JNI:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4096069

JNI-это медленный интерфейс, и поэтому сокеты JAVA TCP являются самым быстрым методом уведомления между приложениями, однако это не означает, что вам нужно отправлять полезную нагрузку через сокет. Используйте LDMA для передачи полезной нагрузки, но как предыдущие вопросы указали, что поддержка Java для отображения памяти не идеальна, и вы так захотите реализовать Библиотеки JNI, чтобы выполнить вызов mmap.

Comments

    Ничего не найдено.