Possible performance gains with JNI?

A year or two ago, I created a program written in Java to simulate an n-body problem. I recently got a crazy idé to rewrite a program as a distributed program in order to be able to more efficiently simulate large masses.

Profiling an old program showed, as expected, that approximately 90% of the program was spent calculating float values. If I remember correctly, C / C ++ is faster than Java when performing arithmetic operations, especially calculations like float.

Anyway, here is the real question :)

Using JNI, can I expect an increase in speed equal to a program written in C / C ++ (for computing), or will the JVM slow it down?

+2
source share
5 answers

Most float operations take about 1 ns in Java, so I'm not sure how much faster you expect them to be in C ++.

However, JNI calls often take about 30 ns, so if you do not perform many floating point operations for each call, you are worth more than you save.

As follows from the following micro-test, after the code warms up, each operation is subnano second.

If you want this to accelerate, you can use several cores and make them 4 times or faster.

public static void main(String[] args) throws Exception { int length = 200000; double[] a = fill(new double[length]); double[] b = fill(new double[length]); double[] c = fill(new double[length]); double[] x = new double[length]; for (int i = 0; i < 10; i++) testTime(length, a, b, c, x); } private static void testTime(int length, double[] a, double[] b, double[] c, double[] x) { long start = System.nanoTime(); for (int i = 0; i < length; i++) x[i] = a[i] * b[i] + c[i]; long time = System.nanoTime() - start; System.out.printf("Average time per double operation was %.1f ns%n", time / 2.0 / length); } private static double[] fill(double[] doubles) { for (int i = 0; i < doubles.length; i++) doubles[i] = Math.random(); return doubles; } 

prints

 Average time per double operation was 10.9 ns Average time per double operation was 17.9 ns Average time per double operation was 1.7 ns Average time per double operation was 1.0 ns Average time per double operation was 0.9 ns Average time per double operation was 0.8 ns Average time per double operation was 0.9 ns Average time per double operation was 0.8 ns Average time per double operation was 1.0 ns Average time per double operation was 0.9 ns 
+5
source

I think this answer: JNI Performance also applies here. If you call JNI, many times perform several calculations each time your performance should suffer. If you call JNI for heavy computing, then optimized C code should run faster.

+3
source

Recently, I recently tested fractal generation (Mandelbrot) with the same code written in Java, and then ported to C, and to my surprise, I observed a slight DECREASE in computational speed when using the JNI method. I can explain this phenomenon with only one: If you use c-code, you cannot use the HotSpot optimization for repeated calculations.

You can check the sample code yourself: http://code.google.com/p/frgenjava/

EDIT: in the situation described, when I use JNI, I ignore the overhead of calling the JNI, which took about 20 ns to call, and even then C was running slower.

+2
source

The most important thing about performance is testing and bench. You have heard that C ++ is better with floating point than with java. Well, that could be so. But without a bench, to show this real difference, it does not cost a dime. It can be really false.

In fact, modern java uses JIT. What is it? Well, we all know that java uses bytecode and that bytecode is interpreted. This is true and false. In fact, heavily used code is compiled on the fly into native code optimized for your platform. JIT can even perform optimizations that are not possible in C / C ++ using runtime statistics.

Java and the JVM are now widely accepted as a truly fast and efficient platform. People are beginning to really use it in heavy computing with success. It is also easier to deploy on a grid.

Recent tests usually show performance similar to C / C ++ (e.g. http://blogs.oracle.com/amurillo/entry/java_vs_c )

So you would benefit from JNI and just port to C ++. I would say no or very little. (But again, a test if you want to be sure). And without its optimization, the C ++ version might be slower.

Can you get significant improvement with JNI and use optimized assembler code (including SEE instructions)? Of course, yes, if you do it right. It will take a lot of scam, experience and time.

+2
source

I cannot comment on the speed of Java arithmetic operations, but I know that JNI will call directly into your C ++ code, so you will get your own speed, yes

+1
source