简体   繁体   中英

Possible increase of performance using JNI?

A year or two ago I created a program written in Java to simulate the n-body problem. Recently I've gotten the crazy idé to rewrite the program as a distributed program to be able to simulate larger masses with better accuracy.

Profiling the old program showed, as expected, that roughly 90% of the program was spent calculating float type values. If I remember correctly C/C++ is ALOT faster then Java at doing arithmetics operations, especially float type calculations.

Anyways, here's the actual question :)

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

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

However JNI calls often take around 30 ns, so unless you are performing alot of floating point operations per call, you will cost more than you save.

As the following micro-benchmark suggests, once the code as warmed up, each operations is sub nano second.

If you want this to go faster, you could use multiple cores and make it 4x or more 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

I think this answer: JNI Performance also applies here. If you are calling JNI many times doing few calculations each time your performance should suffer. If you call JNI for heavy calculations then the C optimized code should perform faster.

I have actually recently tested fractal generation (Mandelbrot) with the same code written in Java and then ported to C and to my surprise, I observed slight DECREASE in speed of computation when using the JNI method. I can explain this phenomenon by only one thing: If you use c code, you can't get advantage of HotSpot's optimization for repeatable computations.

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

EDIT: in the situation I described, when using JNI, I disregard the overhead for a JNI call, which took about 20ns for a call and even then C performed slower.

The most important thing with performance concerns is to test and bench. You have heard that C++ is better at floating point than java. Ok this may be the case. But without a bench to show this actual difference, this is not worth a penny. This could be really false.

In fact, modern java use a JIT. What's that ? Well we all know java use bytecode and that the bytecode is interpreted. This is true and false. In fact heavily used code is compiled on the fly to native code optimised for your platform. The JIT can even perform optimisation not possible in C/C++ by using execution statistics.

Now Java and the JVM is widely accepted as a really fast and effective platform. People start to really use it in heavy computing aera with quite success. It is also easier to deploy on a grid.

Recent benchmarks tend to show performance similar to C/C++ (for exemple http://blogs.oracle.com/amurillo/entry/java_vs_c )

So would you gain from JNI and just porting to C++. I would say no, or very little gains. (But again test if you want to be sure). And without optimising it, the C++ version could be slower.

Could you gain massive improvement by using JNI, and using optimised assembly code (including SEE instructions) ? Definitely yes if you do it the right way. It would need lot of benchs, expertise and time through.

我不能评论Java算术运算的速度,但我知道JNI会直接调用你的C ++代码,所以你会得到原生速度,是的

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM