IPC с графическим интерфейсом (Java & Native code) - PullRequest
3 голосов
/ 20 июня 2011

Мое приложение состоит из 2 частей -

Некоторые логики GUI на Java.Нативный код (в основном Delphi) - сама реализация GUI.

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

Я заинтересован в том, чтобы разделить обе стороны на разные процессы. Как лучше всего реализовать IPC между ними без зависания графического интерфейса?Я склоняюсь к сокетам TCP или разделяемой памяти, но прежде чем я углублюсь в это, я хотел бы услышать некоторый вклад.Производительность и простота реализации - мои главные проблемы.

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 20 июня 2011

Если ваша проблема связана с потреблением памяти

Если вам не хватает оперативной памяти (как это предусмотрено вашими комментариями - но вам лучше было бы написать это в своем основном вопросе: чем больше деталей вы дадите, тем лучше получите ответы).

Почему вы смешиваете Java и Delphi? Java, вероятно, не является хорошим кандидатом для обработки более 1 ГБ памяти из-за более высокого потребления памяти для общих задач и из-за ее внутреннего GC. Даже если вы запустите JVM в 64-битной среде, вы столкнетесь с новыми проблемами масштабирования: вам придется написать очень специфический код для обработки огромной памяти с помощью Java.

Если честно, проблемы не в Delphi, а в потреблении памяти Java. Поэтому ИМХО вам лучше кодировать свой слой данных в нативный код. Java потенциально увеличивает ваши проблемы.

Вы можете либо:

  • Используйте Free Pascal Compiler , чтобы скомпилировать 64-битную библиотеку из кода Delphi, а затем вызвать ее из основного 32-битного приложения Delphi или из Java, используя JNI, используя файл сопоставления памяти в качестве моста .
  • Изменить способ доступа к данным. Вам, вероятно, не нужно будет иметь все эти гигабайты данных одновременно. Вы можете положить его на диск, а затем получить к нему доступ через индексы, которые останутся в оперативной памяти. Если вы используете Delphi, вы должны либо использовать свою собственную обработку файлов (вы можете использовать что-то вроде нашей библиотеки BigTable для хранения и индексированного доступа), либо использовать базу данных (даже SQlite3 способен обрабатывать ГБ данных , поскольку его ограничение составляет около 140 терабайт, что позволяет SQL извлекать только данные).
  • Если вам действительно нужно остаться в Java , вы, вероятно, могли бы использовать некоторые БД вместо простых структур в памяти. Вы можете использовать SQLite из Java или чистый Java DB. Я подозреваю, что это уменьшит ваше потребление памяти.

Основной подход: сохраняйте в памяти только то, что нужно, и работайте с алгоритмами Map / Reduce или какими-то индексами.

Если ваша проблема заключается в смешении графического интерфейса между Java и Delphi

Из моего эксперимента это может быть сложно, поскольку JNI имеет тенденцию использовать свои собственные потоки, а VCL ожидает, что весь его процесс будет выполняться в основном потоке.

Так что вы можете:

  1. Создайте несколько методов Delphi, запустив метод VCL Synchronize при вызове из JNI для обновления экрана.
  2. Положитесь на обмен сообщениями Windows GDI, т. Е. Создайте свой собственный обработчик WM_USER * в коде Delphi, а затем обновите содержимое экрана из своего кода Java, просто отправив низкоуровневый API PostMessage или SendMessage. По замыслу это будет поточно-ориентированным.
  3. Используйте подход без сохранения состояния: мне это очень нравится. Как и в HTTP, ваш пользовательский интерфейс будет выступать в качестве клиента и периодически запрашивать обновленные данные на уровне данных (действующем в качестве сервера). Весь этот процесс останется в главном потоке и может быть легко выполнен через таймер. С таймером достаточно 500 мсек для каждого обновления, и ваше основное приложение будет реагировать.

Во всех случаях ...

Для IPC файлы с отображением в памяти работают быстрее, чем сокеты, но сообщения GDI идеальны, когда речь идет о небольшом объеме данных. Сокеты являются хорошими кандидатами и будут быстрыми также на локальном компьютере: небольшие накладные расходы на файлы с отображением в память не будут заметны, если объем передаваемых данных составляет всего несколько КБ (до 1 МБ, например); и если вам нужно создать облегченную клиентскую версию приложения, оно все равно будет работать.

1 голос
/ 20 июня 2011

Вопрос к вашему ответу зависит от ваших требований (при условии, что у вас есть веские основания для такого разделения заявки):

Если вам нужно выполнить «тривиальные» задачи, т.е. не требовать больших объемов передачи данных, то, вероятно, лучше использовать сокеты. Тем не менее, вам необходимо создать протокол, например, уважать порядки байтов. Также обратите внимание, что передача данных замедлит ваши ответы на графическом интерфейсе.

Если вам нужно передать большие объемы данных, использование общей памяти может быть более производительным. Обратите внимание, что здесь вам нужно самостоятельно вести учет, что осуществляется реализацией tcp (например, буфером приема / передачи). Использование этого Проблема требования протокола становится еще хуже.

0 голосов
/ 20 июня 2011

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

...