为什么我的本地C++代码在Android上运行比Java慢这么多?

4

我将我的一些 Java 代码移植到 C++ 上,以加快在 Android 上的计算速度(这是一个物理子程序)。但我发现本地代码运行的速度比 Java 代码慢几倍。我想也许是项目配置出了问题,或者数组处理有误,所以我在 HelloAndroidJni 项目中放了一个简单的循环来测试原始速度差异,并得到类似的结果。

Java 代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    /* ...generic boilerplate code... */

    TextView tv = (TextView) findViewById(R.id.sample_text);
    int loopCount = 100000;

    //time the native method
    long ticks = System.nanoTime();
    int result = nativeTest(100000);
    long nativeTime = (System.nanoTime() - ticks) / 100000;

    //time the Java method
    ticks = System.nanoTime();
    result = javaTest(100000);
    long javaTime = (System.nanoTime() - ticks) / 100000;

    //present results
    tv.setText("Native=" + nativeTime + "; Java=" + javaTime);
}

The loop in Java:

int javaTest(int count) {
    int result = 0;
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < 100; j++) {
        result += 34432; result++;
        result -= 34431; result--;
    } }
    return result;
}

以下是C++代码:

JNIEXPORT jint JNICALL
Java_com_fringecode_helloandroidjni_MainActivity_nativeTest(
        JNIEnv *env, jobject jThis, jint count) {
    int result = 0;
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < 100; j++) {
            result += 34432; result++;
            result -= 34431; result--;
        } }
    return result;
}

项目的其余部分与HelloAndroidJni示例项目相同。典型运行结果为Native=2580毫秒,Java=195毫秒。是什么导致本地代码比Java运行得慢那么多呢?

编辑:顺便说一句,在模拟器上,本地代码比Java运行得快得多,但在我的手机(LG V20 / Snapdragon 820)上,本地代码要慢得多。


2
你启用了任何编译器优化吗? - kmkim85
也许它仍然被优化了,尝试在返回语句中连接结果并再次测试。而且@DenisDda,JNI调用开销小于1毫秒,所以这不应该是个问题。 - Nabin Bhandari
问题既不是JNI开销,也不是循环被优化掉了。两个循环所需的时间都与loopCount成线性比例。我在这里发布的代码只是为了尝试弄清楚为什么我的实际物理循环运行得更慢。我将尝试使用其他NDK示例进行更多基准测试,并查看它们是否在C中运行得更慢。 - HypnoToad
你为什么要创建并且丢弃一个 std::string?难道你不能直接使用 return env->NewStringUTF("Hello from C++"); 而不浪费额外的动态内存分配和释放吗? - Useless
NDK确实提供了一个性能分析工具:https://developer.android.com/ndk/guides/simpleperf.html - Dan Albert
显示剩余4条评论
1个回答

2

Java的即时编译优化可以使您的循环速度与本地代码一样快。另一方面,如果没有使用APP_OPTIM=release,C++编译器将生成调试未经优化的代码。

结论是,如果以有纪律的方式编码,则Java中的数字计算实际上可能非常高效。但归根结底,以同样的效率在C中编码也需要纪律性。


谢谢,这正是问题所在。我没想到调试版本会比Java代码慢那么多! - HypnoToad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接