У меня есть приложение Java, которое через сокет TCP подключается к «серверу», разработанному на C / C ++.
и приложение, и сервер работают на одном компьютере, в системе Solaris (но в конечном итоге мы рассматриваем возможность перехода на Linux). Тип обмена данными - простые сообщения (логин, авторизация ACK, затем клиент что-то запрашивает, ответы сервера). каждое сообщение имеет длину около 300 байт.
В настоящее время мы используем сокеты, и все в порядке, однако я ищу более быстрый способ обмена данными (меньшая задержка) с использованием методов IPC.
Я исследовал сеть и нашел ссылки на следующие технологии:
- Общая память
- трубы
- очереди
- а также то, что называется DMA (прямой доступ к памяти)
но я не смог найти ни надлежащего анализа их соответствующих характеристик, ни того, как реализовать их как на JAVA, так и на C / C ++ (чтобы они могли разговаривать друг с другом), за исключением, возможно, каналов, которые я мог представить, как это сделать.
может ли кто-нибудь прокомментировать производительность и осуществимость каждого метода в этом контексте? любой указатель / ссылка на полезную информацию о реализации?
ИЗМЕНИТЬ / ОБНОВИТЬ
следуя комментариям и ответам, которые я получил здесь, я нашел информацию о сокетах домена Unix, которые, похоже, построены прямо над каналами и спасут мне весь стек TCP. он специфичен для платформы, поэтому я планирую протестировать его с помощью JNI или с помощью juds или junixsocket .
Следующими возможными шагами будет прямая реализация каналов, а затем общая память, хотя меня предупреждали о дополнительном уровне сложности ...
Спасибо за вашу помощь
Ответы:
Только что протестировали задержку с Java на моем Corei5 2,8 ГГц, только однобайтовые отправка / получение, 2 процесса Java только что порождены, без назначения конкретных ядер ЦП с набором задач:
Теперь явно указываем основные маски, например набор задач 1 java Srv или набор задач 2 java Cli :
так
В то же время Thread.sleep (0) (который, как показывает strace, вызывает выполнение одного вызова ядра Linux sched_yield ()), занимает 0,3 микросекунды, поэтому именованные каналы, запланированные на одно ядро, по-прежнему имеют много накладных расходов.
Некоторые измерения совместно используемой памяти: 14 сентября 2009 г. - Сегодня Solace Systems объявила, что ее API платформы единой системы обмена сообщениями может достигать средней задержки менее 700 наносекунд с использованием транспорта совместно используемой памяти. http://solacesystems.com/news/fastest-ipc-messaging/
PS - попробовал разделяемую память на следующий день в виде файлов с отображением памяти, если занятое ожидание приемлемо, мы можем уменьшить задержку до 0,3 микросекунды для передачи одного байта с помощью следующего кода:
Примечания: Thread.sleep (0) необходим, чтобы 2 процесса могли видеть изменения друг друга (другого способа я пока не знаю). Если 2 процесса принудительно подключены к одному ядру с помощью набора задач, задержка становится 1,5 микросекунды - это задержка переключения контекста
PPS - и 0,3 микросекунды - хорошее число! Следующий код занимает ровно 0,1 микросекунды при выполнении только простой конкатенации строк:
PPPS - надеюсь, это не слишком уж не по теме, но, наконец, я попытался заменить Thread.sleep (0) на инкремент статической изменчивой переменной int (при этом JVM сбрасывает кеши ЦП) и получил - запись! - Связь между процессами Java-Java с задержкой 72 наносекунды !
Однако при принудительном использовании одного и того же ядра ЦП JVM с изменяющимся инкрементом никогда не уступают управление друг другу, таким образом создавая задержку ровно 10 миллисекунд - квант времени Linux кажется 5 мс ... Так что это следует использовать только при наличии запасного ядра - в противном случае sleep (0) безопаснее.
источник
DMA - это метод, с помощью которого аппаратные устройства могут получать доступ к физической памяти, не прерывая работу ЦП. Например, типичным примером является контроллер жесткого диска, который может копировать байты прямо с диска в RAM. Таким образом, это не применимо к IPC.
Совместно используемая память и каналы напрямую поддерживаются современными ОС. Таким образом, они довольно быстрые. Очереди обычно являются абстракциями, например, реализованными поверх сокетов, каналов и / или общей памяти. Это может выглядеть как более медленный механизм, но альтернативой является то , что вы создать такую абстракцию.
источник
Вопрос был задан некоторое время назад, но вас может заинтересовать https://github.com/peter-lawrey/Java-Chronicle, который поддерживает типичные задержки 200 нс и пропускную способность 20 M сообщений в секунду. Он использует файлы с отображением памяти, совместно используемые между процессами (он также сохраняет данные, что делает его самым быстрым способом сохранения данных)
источник
Вот проект, содержащий тесты производительности для различных транспортов IPC:
http://github.com/rigtorp/ipc-bench
источник
Если вы когда-нибудь задумывались об использовании собственного доступа (поскольку и ваше приложение, и «сервер» находятся на одной машине), подумайте о JNA , у нее меньше шаблонного кода, с которым вам придется иметь дело.
источник
Позднее прибытие, но хотелось бы отметить проект с открытым исходным кодом, посвященный измерению задержки ping с помощью Java NIO.
Более подробно исследовано / объяснено в этом сообщении в блоге . Результаты (RTT в нано):
Это соответствует принятому ответу. Ошибка System.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.
источник