Issue
I was absolutely sure that C\C++ native code will run faster than Java code. And it is. My simple C/C++ benchmark (random arithmetic operations on int array) runs 5-7 times faster than the same Java code on an old tablet (Samsung Galaxy Tab E - Android 4.4.4 - Dalvik VM), but slower on recent devices with ART Prestigio K3 Muze (Android 8.1) & Samsung S21 Ultra (Android 11).
Why Android Runtime compiled code runs faster than native C/C++ code (Android NDK / JNI)?
Java code:
public void calculateJava(int size) {
int[] array = new int[size];
int sum = 0;
for (int i=0; i<size; i++) {
array[i] = i;
for (int j=0; j<size; j++) {
sum += array[i] * array[j];
sum -= sum / 3;
}
}
}
C/C++ code (JNI):
extern "C" JNIEXPORT void JNICALL Java_com_axiom_firstnative_MainActivity_calculateNative(
JNIEnv* env,
jobject,
jint size) {
int* array = new int[size];
jint sum = 0;
for (jint i=0; i<size; i++) {
array[i] = i;
for (jint j=0; j<size; j++) {
sum += array[i] * array[j];
sum -= sum / 3;
}
}
// delete[] array;
}
OnClick (Java)
long startTime = System.nanoTime();
calculateNative(4096);
long nativeTime = System.nanoTime() - startTime;
startTime = System.nanoTime();
calculateJava(4096);
long javaTime = System.nanoTime() - startTime;
String report = "VM:" + System.getProperty("java.vm.version")
+ "\n\nC/C++: " + nativeTime
+ "ns\nJava: " + javaTime + "ns\n"
+ "\nJava to C/C++ ratio "
+ ((double) javaTime / (double) nativeTime);
Results:
Samsung Galaxy Tab E (Android 4.4.4) - Java time: 2166748ns , C/C++ time: 396729 ns (C/C++ 5 times faster)
but
Prestigio K3 Muze (Android 8.1) on first start - Java time:3477001ns, C/C++ time: 547692ns (C/C++ 6 times faster), but after warm up Java runs 30-40% faster.
Samsung Galaxy S21 Ultra (Android 11) - Java time: 111000ns, C/C++ time: 121269ns (Java 9% faster on first start and 40-50% faster after warm up!!!)
Turning on CLang compiler optimization options (-O3) makes C/C++ run ~30-35% faster (Android 8.1) than Android Runtime optimized Java code. But still, on Android 11 ART optimized code runs 10-20% faster than CLang C/C++ optimized (-O3) native code. That is mind-blowing...
p.s. Both benchmarks run sequentially on one thread, so I suppose they use the same core.
Question:
How Android Runtime compile more efficient native code than CLang compiler?
Is there any performance advantage in writing native C/C++ code on recent Android OS versions?
Solution
How Android Runtime compile more efficient native code than CLang (Android NDK) C/C++ compiler?
The JIT compiler complements ART's current ahead-of-time (AOT) compiler and improves runtime performance.
Although JIT and AOT use the same compiler with a similar set of optimizations, the generated code might not be identical. JIT makes use of runtime type information can do better inlining and makes on stack replacement (OSR) compilation possible, all of which generate slightly different code.
Is there any performance advantage in writing native C/C++ code on recent Android OS versions?
Definitely yes for old Android devices. Old Android devices use Dalvik VM that interprets code. Java code will be 5-7 times slower than the same C/C++ code on Dalvik VM. But on ART, in most cases, Android Runtime profile-guided compilation generates much more efficient native code based on application execution statistics, but Java still ~30-35% slower than optimized C/C++ code on Android 8.1 and ~10-20% faster on Android 11.
https://source.android.com/devices/tech/dalvik/jit-compiler
Conclusion: In my humble opinion, there is no performance advantage in writing C/C++ code for recent Android devices (starting from v7.0 Nougat - ART VM), unless you're an experienced C/C++ developer and deeply understand CPU architecture, so you can do optimization much better than Android Runtime does.
Also, Android NDK (C/C++) is still the only way for Android Developers to:
- Port your native C/C++ code to Android.
- Use C/C++ game engines and libraries (like Vulkan or TensorFlow).
- Use platform-specific APIs not available in Android SDK.
Answered By - Bolat Basheyev
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.