【发布时间】:2021-07-29 02:14:09
【问题描述】:
我绝对确信 C\C++ 原生代码将比 Java 代码运行得更快。它是。我的简单 C/C++ 基准测试(int 数组上的随机算术运算)比旧平板电脑(Samsung Galaxy Tab E - Android 4.4.4 - Dalvik VM)上的相同 Java 代码运行速度快 5-7 倍,但在最近的设备上运行速度较慢ART Prestigio K3 Muze(Android 8.1)和三星 S21 Ultra(Android 11)。
为什么 Android Runtime 编译的代码比原生 C/C++ 代码(Android NDK / JNI)运行得更快?
Java 代码:
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++ 代码 (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);
结果:
Samsung Galaxy Tab E (Android 4.4.4) - Java 时间:2166748ns,C/C++ 时间:396729 ns(C/C++ 快 5 倍)
但是
首次启动时 Prestigio K3 Muze (Android 8.1) - Java 时间:3477001ns,C/C++ 时间:547692ns(C/C++ 快 6 倍),但预热后 Java 运行速度快 30-40%。
Samsung Galaxy S21 Ultra (Android 11) - Java 时间:111000ns,C/C++ 时间:121269ns(Java 首次启动快 9%,预热后快 40-50%!!! )
启用 CLang 编译器优化选项 (-O3) 可使 C/C++ 的运行速度 (Android 8.1) 比 Android 运行时优化的 Java 代码快约 30-35%。但是,在 Android 11 上,ART 优化代码的运行速度比 CLang C/C++ 优化 (-O3) 本机代码快 10-20%。这真是令人兴奋......
附言两个基准测试都在一个线程上按顺序运行,所以我想它们使用相同的内核。
问题:
Android Runtime 如何编译出比 CLang 编译器更高效的原生代码?
在最新的 Android 操作系统版本上编写本机 C/C++ 代码是否有任何性能优势?
【问题讨论】:
-
较新的手机具有分速 CPU - 您需要检查您的内核在哪个内核上运行。
-
我无法理解你的结论:如果 Java 需要 396729ns=397µs 和 C++ 2166748ns=2167µs,为什么你说 C++ 更快?它需要更长的时间。 (第二组数字相同。)
-
我在统计上犯了一个错误。反之亦然 (Java/C++) 在前两个示例中。固定。
-
我找到了关于该主题的研究:“为了回答研究问题,根据实验结果,我们可以看到,在所选择的算法中,最快的算法之间没有显着的性能差异Java 的 FFT 库及其在本机代码中的相应实现。本机代码中的优化确实使本机代码比最快的 Java 实现快得多。这确实增加了代码的复杂性并降低了设备之间的兼容性。 diva-portal.org/smash/get/diva2:1109257/FULLTEXT01.pdf
-
您应该发布完整的基准代码以获得更好的答案,因为缺少很多细节。例如,您没有提到 C++ 的优化级别,就像@RichardCritten 提到您是否在同一个核心上运行测试。此外,您在返回之前调用了 delete[],这意味着 C++ 函数的行为不同。
标签: java android c++ c android-ndk