开发者

Performance of C++ calls to Java code vs C# code

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!


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.


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 :

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

with theCPPWrapper.GetField(string) returning a JNI Field class and the Field.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 :

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

Whatever you consider, first check that your native API isn't unnecessarily chatty, or your GC will suffer.

Cheers, Florian


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.


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.


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:

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

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).


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜