C++调用Java代码和C#代码的性能比较

3
我正在研究一个客户的解决方案,我们需要从C++应用程序调用既可在C#又可在Java上使用的API。 我们希望这是一个跨平台的应用程序(PC和Mac),因此优先选择Java,但性能更重要。我一直在试图研究C++调用C#与Java的性能比较,但没有找到任何可靠的信息。使用JNI调用Java API或使用托管的C++调用C# API是可行的想法。
是否有人可以提供关于哪个更好的性能信息或见解? 这些调用可能会频繁执行,因此卷数也是一个考虑因素。
谢谢!

据我所知,你无法使用JNI从C/C++中调用Java。而是相反的:JNI使您能够调用使用C/C++编写的库。 - musiKk
4
JNI也允许你实例化一个JVM并从C代码中调用它。 - Romain Hippeau
你可以从C++中调用Java,但是如果性能很重要,就要减少调用次数。大多数任务都可以重新组织,以减少调用次数。如果你的代码写得好,这些调用的成本不应该很高。对于JNI,成本可能约为30个时钟周期,但这实际上取决于你正在做什么。 - Peter Lawrey
1
只要避免使用System.Windows.Forms.*子空间,你也可以在Mac上使用C#。微软从一开始就提供了这个功能,并且自己也在使用它。既然你关心性能,那么你不需要编写GUI类型的代码,为什么不使用你熟悉的任何一种呢? - Joe Zitzelberger
6个回答

4
我无法给出确定的答案,但我曾经使用 JNI 调用 C 库(不是反过来),.NET 调用封装的 Java 库和 .NET 调用 .NET 库。虽然我没有官方数据,但调用 .NET 库(无论是托管 C++ 还是 C#)都是最简单和最快的。因为它们都属于 .NET,因此两边都支持一组通用的数据类型。而在其他情况下,需要很多丑陋的编组代码来转换不同语言之间的数据类型。.NET Framework 的设计初衷是使不同的 .NET 库之间的调用透明化,并且这样做非常好。
另一个考虑因素是,在高容量环境中,个别库的性能可能比互操作性能更令人关注。换句话说,如果 Java 库比 C#库快 25%,即使与 C#相比,与 Java 的交互操作更快且更容易,使用 Java 库也是有意义的。

1

我没有关于C#转Java的度量标准。然而,我们有很多调用C++转Java的经验。即使在缓存了所有类和方法ID之后,它仍然非常慢。C++/JNI调用似乎需要大约1000个时钟周期,并且我们观察到限制为每秒约3M次调用。因此,我们已经进行了许多优化迭代,涉及将数据块一次性传输到Java中。此外,您必须检查Java异常或至少在返回时重置异常状态,这会增加另一个开销。

另一方面,从Java调用C++非常快。如果可以这样做,请使用它。还有一些高级技术涉及“continuations”,其中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方法,但这些方法也往往会相对较慢地达到最大值(大约1M /秒)。


1

我认为C#和Java的API是相同的。我曾经在一个环境中工作,其中C#和Java都必须通过interop / JNI与同一个C++库进行通信。似乎当涉及到性能时,Java版本更加一致,因为API非常善于交流并生成了许多瞬态对象。

这就是我们的调用方式:

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

使用theCPPWrapper.GetField(string)返回一个JNI Field类,而Field.AsDouble()方法则需要通过另一层交互来实现,这样做没有任何意义...

因此,GC中充满了短暂的Field对象,而Java似乎更能应对这种情况。

最终的解决方案是改变JNI / Interop api的方式:

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

无论你考虑什么,首先要检查你的本地API是否过于啰嗦,否则你的GC会受到影响。

祝好, Florian


0
如果您需要管理多种语言之间的复杂调用,我建议使用一个抽象层来分离所有调用。
我曾在同样的情况下成功地使用了CORBA和XML-RPC,它们都得到了很好的支持和文档。但是在选择之前,您需要研究它们各自的优缺点。

0

-1

在 Mac 上调用 C# 代码的计划是什么?还是你会在 Mac 上使用 Java,而在 Windows 上使用 C#?只是好奇你愿意承担哪些支持要求。我希望从非托管 C++ 调用托管 C++ 应该相当高效,但我承认我从未这样做过。


基本上,我们可以使用Java API来支持Windows和Mac,或者使用C#仅支持Windows。客户希望启用Mac支持,但性能优先于环境。 - wezman
至少在 .Net 1.0、1.1 和 2.0 时代,CLR 和命令行 (csc) 编译器可供 Mac 下载使用。除了 System.Windows.Form.* 之外,其他都可以使用。 - Joe Zitzelberger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接