C++ 的性能Java 代码调用与 C# 代码调用
我正在为客户探索一种解决方案,我们必须从 C++ 应用程序调用 C# 和 Java 中都可用的 API。我们希望这是一个跨平台应用程序(PC&Mac),因此Java是首选,但性能更重要。我一直在尝试对 C++ 调用 C# 与 Java 的性能进行一些研究,但尚未找到任何可靠的信息。这个想法是使用 JNI 来调用 Java API 或托管 C++ 来调用 C# API。
有谁知道什么是更好的性能方面的信息或见解吗?这些调用可能会被大量执行,因此数量确实会发挥作用。
谢谢!
I am exploring a solution at my client where we have to call an API that is available in both C# and Java from our C++ application. We would like this to be a cross platform application (PC & Mac), so Java is preferred, but performance is more important. I've been trying to do some research on the performance of C++ calls to C# vs Java but haven't found any solid information. The idea is to use JNI to call the Java API or managed C++ to call the C# API.
Does anyone out there have information or insight as to what would be better performance wise? These calls will potentially be performed heavily, so volume does come into play.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我无法为您提供明确的答案,但我已经完成了 JNI 到 C 库的调用(而不是相反)、.NET 到包装 Java 库的调用以及 .NET 到 .NET 库的调用。我没有关于其中任何一个的官方数据,但是 .NET 到 .NET 的调用,无论是托管 C++ 还是 C# 都是最简单、最快的。因为它们都是 .NET,所以双方都支持一组通用的数据类型。在其他情况下,需要大量丑陋的编组代码来在不同语言的数据类型之间进行转换。 .NET Framework 的设计初衷是让不同 .NET 库之间的调用对其原始语言是透明的,并且它在这方面做得很好。
另一个考虑因素是,在大容量环境中,各个库的性能可能比互操作性能更值得关注。换句话说,如果 Java 库比 C# 库快 25%,那么即使与 C# 的互操作比与 Java 更快、更容易,使用 Java 库也可能是有意义的。
I cannot offer you a definitive answer, but I have done JNI to C library calls (not the reverse), .NET to wrapped Java library calls, and .NET to .NET library calls. I don't have official numbers on any of them, but the .NET to .NET calls, whether managed C++ or C# were both the easiest and fastest. Because they were both .NET, there was a common set of datatypes supported on both sides. In the other instances, there was lots of ugly marshaling code required to convert between datatypes in different languages. The .NET Framework was designed with the intent that calls between different .NET libraries would be transparent of their original language and it does this very well.
Another consideration is that in a high-volume environment, the performance of the individual libraries may be a bigger concern than the interop performance. In other words, if the Java library is 25% faster than the C# library, it may make sense to use the Java library even if the interop with C# is faster and easier than with Java.
我假设 C# 和 Java API 是相同的。我曾经在 C# 和 Java 都必须通过互操作/JNI 与同一个 C++ 库对话的环境中工作。就性能而言,Java 版本似乎更加一致,因为 API 非常繁琐并且生成了很多瞬态对象。
这就是我们的调用的样子:
theCPPWrapper.GetField(string)
返回一个 JNIField
类,并且Field.AsDouble()
方法正在运行毫无意义地通过另一层互操作...因此 GC 充满了瞬态 Field 对象,并且不知何故 Java 似乎能够更好地应对。
最后的解决方法是将 JNI / Interop api 更改为如下所示:
无论您考虑什么,首先检查您的本机 API 是否没有不必要的麻烦,否则您的 GC 将受到影响。
干杯,
弗洛里安
I assume the C# and Java API are the same. I used to work in an environment where both C# and Java had to talk to the same C++ library through interop / JNI. It seems the Java version was more consistent when it came to performance, as the API was quite chatty and generated a lot of transient objects.
This is what our calls looked like :
with
theCPPWrapper.GetField(string)
returning a JNIField
class and theField.AsDouble()
method going through yet another layer of interop for nothing...So the GC was full of transient Field objects and somehow Java seemed to cope better.
In the end the fix was to change the JNI / Interop api to look thus :
Whatever you consider, first check that your native API isn't unnecessarily chatty, or your GC will suffer.
Cheers,
Florian
我没有 C# 到 Java 的指标。然而,我们在调用 C++ 到 Java 方面拥有丰富的经验。即使您缓存了所有类和方法 ID,速度也非常慢。 C++/JNI 调用似乎需要大约 1000 个时钟周期,我们观察到每秒大约 3M 调用作为限制。因此,我们经历了多次优化迭代,涉及在一次调用中将数据块传输到 Java。此外,您必须检查 Java 异常,或者至少在返回时重置异常状态,这又增加了一点开销。
另一方面,从 Java 调用 C++ 的速度非常快。如果你能做到这一点,那就去做吧。有一些涉及 Java 和 C++ 反转控制的“延续”的高级技术。它是这样的:
这种控制反转并不适合许多(大多数?)应用程序,但它是另一个想法。您还可以考虑各种 RPC 方法,但这些方法也往往会相当缓慢地达到最大值(1M/秒左右)。
I have no metrics for C#-to-Java. However, we have a lot of experience calling C++-to-Java. It is incredibly slow, even after you cache all of your class and method IDs. The C++/JNI call seems to take about 1000 clock cycles, and we observed about 3M calls/second as a limit. Because of this, we've gone through many iterations of optimization involving transporting blocks of data to Java in one call. In addition, you MUST check for Java exceptions or at least reset the exception state upon return, which adds another bit of overhead.
On the other hand, calling C++ from Java is incredibly fast. If you can do that instead, do it. There are some advanced techniques involving "continuations" in which the Java and C++ invert control. It goes like this:
This inversion of control is not suitable for many (most?) applications, but it is another idea. You can also consider various RPC approaches, but these will also tend to max out fairly slowly (1M/second or so).
如果您要管理所有语言之间的多个复杂调用,我建议使用抽象层来分隔所有调用。
我在相同的情况下成功使用了 CORBA 和 XML-RPC,两者都得到了很好的支持/记录。
但他们有优点和缺点。在选择一之前你要先研究一下缺点。
If you will manage several and complex calls between all languages I suggest the use of an abstraction layer that separate all calls.
I used CORBA and XML-RPC in same situation with success, both are well supported/documented.
But they have pros & cons that you will study before choice one.
有很多比较 C/C++ 和 Java 的基准测试。 (第二个也包括C#)
注意:这些只是基准,应该持保留态度。
http://www.idiom.com/~zilla/Computer/javaCbenchmark.html< /a>
http://reverseblade.blogspot.com/ 2009/02/c-versus-c-versus-java-performance.html
与通过转换层相比,在一个环境中完成所有操作总是更快。当然,如果你开始进行远程调用,它总是会慢很多。这个想法是,如果要进行串扰,请保持高粒度。
There are quite a few benchmarks comparing C/C++ and Java. (The second one also includes C#)
NOTE: These are just benchmarks and should be taken with a grain of salt.
http://www.idiom.com/~zilla/Computer/javaCbenchmark.html
http://reverseblade.blogspot.com/2009/02/c-versus-c-versus-java-performance.html
Doing everything in one environment is always faster, compared to going through a conversion layer. Of course if you start doing remote calls it will always be a lot slower. The idea is to keep granularity high if you are going to cross-talk.
在 Mac 上调用 C# 代码的计划是什么?或者您会在 Mac 上使用 Java,在 Windows 上使用 C#?只是对您愿意满足的支持要求感到好奇。我希望从非托管 C++ 调用托管 C++ 会相当有效,但我承认我从未这样做过。
What's the plan for calling C# code on the Mac? Or would you use Java on the Mac and C# for Windows? Just curious about the support requirements you're willing to rack up. I would hope that calling managed C++ from unmanaged C++ would be fairly efficient, but I confess I've never done it.