itun
itun

Reputation: 3521

Java+JNI opposite Pure C++

I make a DLL-Java communication correspondingly this post. My compilation configuration you can see there:

    g++ -IC:\Users\RZ\Downloads\eigen-eigen-3.0.3\eigen-eigen-3.0.3 -IC:\Program Files\Java\jdk1.7.0\include\win32 -IC:\Program Files\Java\jdk1.7.0\include -O3 -msse -msse2 -mmmx -Wall -shared -c -o Vector3DImp.o ..\Vector3DImp.cpp
..\Vector3DImp.cpp:5:0: warning: "JNICALL" redefined
C:\Program Files\Java\jdk1.7.0\include\win32/jni_md.h:31:0: note: this is the location of the previous definition
g++ -Wl,--kill-at -shared -LC:\Program Files\Java\jdk1.7.0\lib -o Eigen.dll Vector3DImp.o

And then I write the same on Java. And launch a few tests with vector multiplication and vector addition: the result is:

Pure java 39 -38 ms

JNI Java 52 -50ms

Then I code the same test on C++ using the same code in DLL. Result:

22 – 18 ms

Yeah the test strategy make seem rough, but the common result is sustainable. Is there my fault or it is JNI drawback (I'm not good at it).

Note:

The main question is: Is it real the DLL use in Java is so hard (the performance reduces by 2.5 times). Why it is?

UPDATE:

At the request, there is source of test. Sorry for mess there, it was made for my own need in short time.

My system configuration: Windows 7 x32, Core 2 Duo.

Both Java and C++ projects were built in Eclipse IDEs with MingW Compiler for C++. For C++ vector calculation Eigen library was used. Also, I tried JBlas library, in the end of Java test it was awful, I don't know why. Even with 3 multiplication operation (opposite 6 multiplication in cross product) the result was creepy. Look yourself.

Upvotes: 1

Views: 608

Answers (4)

clstrfsck
clstrfsck

Reputation: 14847

After having a look at the code you posted, I don't think there is a huge amount you can do to speed this up. The fundamental problem is, as others have said, there is a significant overhead in traversing the Java <-> JNI boundary, and the amount of work being done on the JNI side for a vector multiplication is not enough to amortise this cost.

I did notice that using raw arrays, like this:

List<Vector3DJava> vector3dJavas = new ArrayList<Vector3DJava>();
// Populate list with 1,000,000 random elements
Vector3DJava[] v3dj = vector3dJavas.toArray(new Vector3DJava[vector3dJavas.size()]);
long time = System.nanoTime();
for (int i = 0; i < L; i++) {
    v3dj[i].getMultiplication(v3dj[i+1]);
}
System.out.println((System.nanoTime() - time) / 1000000L);

takes about half the time of this:

List<Vector3DJava> vector3dJavas = new ArrayList<Vector3DJava>();
// Populate list with 1,000,000 random elements
long time = System.nanoTime();
for (int i = 0; i < L; i++) {
    vector3dJavas.get(i).getMultiplication(vector3dJavas.get(i+1));
}
System.out.println((System.nanoTime() - time) / 1000000L);

At least on my machine.

Upvotes: 0

Daniel Voina
Daniel Voina

Reputation: 3215

There are several factors that negatively impact the speed with JNI

  1. Data conversion between DLL and JVM. Your native DLL is little endian while JVM is a big endian so conversions are always performed. Sorry bu here is nothing left for improvement.

  2. The passing of JNIEnv is quite time consuming

There are alternatives to JNI as JNA or CNI but do not expect massive improvements as the basic problem of passing data still remains. The major optimization here is to reduce either the number the calls to the native library or to pack parameters in a format that is friendly to both worlds.

Upvotes: 0

jefflunt
jefflunt

Reputation: 33954

JNI is another layer in your software stack. Not sure why you would want to use it unless you had to. Typically JNI is used to access other non-Java code libraries (DLLs that already exist, that do some complicated thing for you - say if you wanted your software to use DirectX on Windows - you could wrap it using JNI).

I guess what I'm saying is, I'm not terribly surprised that there's some performance overhead, and I don't think it's your fault really. There are performance hits anytime you have to make what are referred to as "system" calls, that is, calls to system resources (or DLLs, or some I/O, etc.) outside of the JVM.

Upvotes: 2

Dave Newton
Dave Newton

Reputation: 160271

Without knowing what you're actually doing, tough to say-but if you're passing parameters between Java and C there will be marshalling/conversion overhead.

Upvotes: 0

Related Questions