Производительность вызовов C ++ для кода Java против кода C # - PullRequest
3 голосов
/ 13 июля 2010

Я изучаю решение на моем клиенте, где мы должны вызвать API, который доступен как в C #, так и в Java из нашего приложения C ++. Мы хотели бы, чтобы это было кроссплатформенное приложение (ПК и Mac), поэтому Java предпочтительнее, но производительность важнее. Я пытался провести некоторое исследование производительности вызовов C ++ к C # против Java, но не нашел никакой достоверной информации. Идея состоит в том, чтобы использовать JNI для вызова API Java или управляемого C ++ для вызова API C #.

Есть ли у кого-нибудь информация или понимание того, что было бы лучше с точки зрения производительности? Эти вызовы потенциально могут быть выполнены интенсивно, поэтому громкость входит в игру.

Спасибо!

Ответы [ 6 ]

4 голосов
/ 13 июля 2010

Я не могу предложить вам точного ответа, но я сделал вызовы из библиотеки JNI в C (не наоборот), вызовы из .NET в библиотеку Java и вызовы из .NET в библиотеку .NET.У меня нет официальных номеров ни на одном из них, но звонки с .NET на .NET, независимо от того, управляются ли они C ++ или C #, были самыми простыми и быстрыми.Поскольку они оба были .NET, с обеих сторон поддерживался общий набор типов данных.В других случаях было много уродливого кода маршалинга, необходимого для преобразования типов данных в разные языки..NET Framework был разработан с намерением, чтобы вызовы между различными библиотеками .NET были прозрачными для их исходного языка, и он делает это очень хорошо.

Другое соображение заключается в том, что в среде большого объема производительностьотдельные библиотеки могут быть более серьезной проблемой, чем производительность взаимодействия.Другими словами, если библиотека Java на 25% быстрее, чем библиотека C #, может иметь смысл использовать библиотеку Java, даже если взаимодействие с C # быстрее и проще, чем с Java.

1 голос
/ 13 июля 2010

Я предполагаю, что C # и Java API одинаковы.Раньше я работал в среде, где и C #, и Java должны были общаться с одной и той же библиотекой C ++ через interop / JNI.Кажется, что версия Java была более последовательной, когда дело доходило до производительности, поскольку API был довольно болтливым и генерировал много временных объектов.

Вот как выглядели наши вызовы:

double myDouble= theCPPWrapper.GetField("foo").AsDouble(); 

с theCPPWrapper.GetField(string) возвратом класса JNI Field и метода Field.AsDouble(), проходящего еще один уровень взаимодействия даром ...

Таким образом, сборщик мусора был полон переходных объектов Field и каким-то образом Java казалсясправиться лучше.

В конце концов, исправление было изменить интерфейс API JNI / Interop, чтобы он выглядел так:

double myDouble = theCPPWrapper.GetFieldAsDouble("foo"); // no transient Field. Yay!

Что бы вы ни думали, сначала убедитесь, что ваш родной API не слишком болтлив.или ваш GC пострадает.

Приветствия, Флориан

0 голосов
/ 18 октября 2015

У меня нет метрик для C #-Java.Тем не менее, у нас есть большой опыт вызова C ++ - в Java.Это невероятно медленно, даже после того, как вы кешируете все свои идентификаторы классов и методов.Вызов C ++ / JNI, кажется, занимает около 1000 тактов, и мы наблюдали около 3M вызовов в секунду в качестве ограничения.Из-за этого мы прошли много итераций оптимизации, включающей передачу блоков данных в Java за один вызов.Кроме того, вы ДОЛЖНЫ проверять наличие исключений в Java или, по крайней мере, сбрасывать состояние исключения по возвращении, что добавляет еще одну дополнительную нагрузку.

С другой стороны, вызов C ++ из Java невероятно быстр.Если вы можете сделать это вместо этого, сделайте это.Есть несколько продвинутых методов, включающих «продолжения», в которых Java и C ++ инвертируют управление.Это выглядит так:

C++ -> Java: Start the continuation loop
   Java: while some condition
      Java -> C++: What do you want me to do
      C++: please do this action for me
      Java does the action

Эта инверсия управления не подходит для многих (большинства?) Приложений, но это другая идея.Вы также можете рассмотреть различные подходы RPC, но они также будут иметь тенденцию к довольно медленному увеличению (1 М / с или около того).

0 голосов
/ 13 июля 2010

Каков план вызова кода C # на Mac? Или вы бы использовали Java на Mac и C # для Windows? Просто любопытно о требованиях поддержки, которые вы готовы набрать. Я надеюсь, что вызов управляемого C ++ из неуправляемого C ++ будет достаточно эффективным, но я признаюсь, что никогда не делал этого.

0 голосов
/ 13 июля 2010

Существует довольно много тестов, сравнивающих C / C ++ и Java.(Второй также включает в себя C #) ПРИМЕЧАНИЕ. Это всего лишь эталонные тесты, которые следует использовать с небольшим количеством соли.

http://www.idiom.com/~zilla/Computer/javaCbenchmark.html
http://reverseblade.blogspot.com/2009/02/c-versus-c-versus-java-performance.html

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

0 голосов
/ 13 июля 2010

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

Я использовал CORBA и XML-RPC в той же ситуации с успехом, оба хорошо поддерживаются / документированы. Но у них есть плюсы и минусы, которые вы изучите, прежде чем выбрать один.

...