AndroidランタイムとNDKのパフォーマンス

Android用のゲームエンジンを開発している間、ネイティブのC / C ++コードは同様のJavaコードよりも高速に実行されると確信していました。この声明は真実ですが、Androidの最新バージョンには当てはまりません。なぜこれが起こっているのかを確認するために、私は少し調査することにしました。





テストでは、Android Studio4.1.3を使用しました-JavaAndroid SDK(API 30)、C / C ++ Android NDK(r21、CLangコンパイラ)。このテストは、2つのネストされたループ内のint配列に対して算術演算を実行する非常に馬鹿げています。意味のある具体的なものはありません。





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++ ( Java GC):





extern "C" JNIEXPORT void JNICALL Java_com_axiom_firstnative_MainActivity_calculateNative(
        JNIEnv* env,
        jobject,
        jint 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;
        }
    }

    // delete[] array;
}

      
      



, 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 time: 2 166 748 ns

C/C++ time: 396 729 ns (C/C++ 5 )





Prestigio K3 Muze (Android 8.1):

Java time: 3 477 001ns ( )

C/C++ time: 547 692ns (C/C++ 6 ),

Java 30-40% (?).





Samsung Galaxy S21 Ultra (Android 11):

Java time: 111 000ns

C/C++ time: 121 269ns

: Java 9% 40-50% C/C++ .





CLang (-O3)  C/C++ ~30-35% (Prestigio K3 Muze Android 8.1) Java , .





Smasung Galaxy S21 Ultra (Android 11) Java 10-20% /C++ CLang (-O3). ...





p.s. , , CPU.





, Java Android C/C++ ? ?

. Android Runtime Ahead-of-Time Java , Just-In-Time . . :





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.





Java NDK C/C++ ?

Dalvik VM仮想マシン(Android 7.0まで)を搭載した古いデバイスの場合は、間違いなくそうです。新しいデバイスの場合、Androidバージョンが7.0よりも高い(ARTランタイムが使用されている)場合、CPUの動作を深く理解し、作成できる経験豊富なC / C ++開発者でない限り、これはあまり意味がありません。 Androidランタイムよりも優れた最適化。そして、次の場合を除いて、ゲームはろうそく(効果/努力)の価値がありません:





  • 既存のC / C ++アプリケーションをAndroidに移植しています





  • Javaでは利用できないC / C ++ライブラリを使用したい





  • AndroidSDKで利用できないAPIを使用したい





PS何かご意見がございましたら、コメントさせていただきます。








All Articles