JNI最適化の局所静的変数,MethodId,FeildId
3102 ワード
このテスト例では、Javaループ呼び出しJNIメソッドを使用して、Javaを呼び出す静的メソッドによって文字列を取得します.Activityコード:
JNIコード:
1、最適化前のjclass cls=env->FindClass(「com/sdke/fixdavid/MainActivity」)jmethodID jmd = env->GetStaticMethodID(cls, “getTestFromJava”, “()Ljava/lang/String;”); JNIメソッドを呼び出すたびにFindClassと取得メソッドIdが実行されます.テスト結果は、JNIが計算した200000文字列の読み出し時間差:15280です.
2、FindClassをGetObjectClass jclass=env->GetObjectClass(object)に変更する.試験結果:JNIが計算した200000文字列の読み出し時間差:9651
3、局所静的変数を用いてMethodIdをコード中のstatic jmethodID jmd=NULLのように記憶する.ローカル静的変数は、メソッドが最初に実行されたときに初期化され、アプリケーションのクローズに伴って破棄されます.
ローカル静的変数のライフサイクル:
1、初期化、関数は初めて2、終了し、役割ドメインは破棄されたが、この変数はプログラムが終了するまでメモリに存在する.
テスト結果:JNIが計算した200000文字列の読み出し時間差:6536
まとめ:1、GetObjectClass性能がFindClass 2より優れている、プログラムがMethodIDまたはFieldIDを複数回呼び出す場合、静的変数記憶を使用して、実行するたびに呼び出さないようにする
補足:
GetObjectClassのclassをグローバル変数として作成し、クラスを作成するたびにglobalClass=(jclass)env->NewGlobalRef(cls)を最適化します.
テスト結果:JNIが計算した200000文字列の読み出し時間差:4742
関連資料:JNIグローバルローカル変数、強弱引用
public void testClick(View v) {
long start = System.currentTimeMillis();
JNI jni = new JNI();
for (int i = 0; i < 2000000; i++) {
jni.testCacheString(MainActivity.this);
}
long end = System.currentTimeMillis();
Log.e(TAG, "JNI 2000000 :" + (end - start));
}
public static String getTestFromJava() {
//Log.e(TAG, " String:----------------------");
return "o(* ̄︶ ̄*)o";
}
JNIコード:
Java_com_sdke_fixdavid_JNI_testCacheString(JNIEnv *env, jobject instance, jobject object) {
static jmethodID jmd = NULL;
// jclass cls = env->FindClass("com/sdke/fixdavid/MainActivity");
jclass cls = env->GetObjectClass(object);
if (jmd == NULL) {
jmd = env->GetStaticMethodID(cls, "getTestFromJava",
"()Ljava/lang/String;");
LOGE(" Method -------------------");
}
jstring job = (jstring) env->CallStaticObjectMethod(cls, jmd);
return job;
}
1、最適化前のjclass cls=env->FindClass(「com/sdke/fixdavid/MainActivity」)jmethodID jmd = env->GetStaticMethodID(cls, “getTestFromJava”, “()Ljava/lang/String;”); JNIメソッドを呼び出すたびにFindClassと取得メソッドIdが実行されます.テスト結果は、JNIが計算した200000文字列の読み出し時間差:15280です.
2、FindClassをGetObjectClass jclass=env->GetObjectClass(object)に変更する.試験結果:JNIが計算した200000文字列の読み出し時間差:9651
3、局所静的変数を用いてMethodIdをコード中のstatic jmethodID jmd=NULLのように記憶する.ローカル静的変数は、メソッドが最初に実行されたときに初期化され、アプリケーションのクローズに伴って破棄されます.
ローカル静的変数のライフサイクル:
1、初期化、関数は初めて2、終了し、役割ドメインは破棄されたが、この変数はプログラムが終了するまでメモリに存在する.
テスト結果:JNIが計算した200000文字列の読み出し時間差:6536
まとめ:1、GetObjectClass性能がFindClass 2より優れている、プログラムがMethodIDまたはFieldIDを複数回呼び出す場合、静的変数記憶を使用して、実行するたびに呼び出さないようにする
補足:
jclass globalClass = NULL;
extern "C"
JNIEXPORT jstring JNICALL
Java_com_sdke_fixdavid_JNI_testCacheString(JNIEnv *env, jobject instance, jobject object) {
static jmethodID jmd = NULL;
// jclass cls = env->FindClass("com/sdke/fixdavid/MainActivity");
// jclass cls = env->GetObjectClass(object);
// jmethodID jmd = env->GetStaticMethodID(cls, "getTestFromJava",
// "()Ljava/lang/String;");
if (jmd == NULL) {
jclass cls = env->GetObjectClass(object);
globalClass = (jclass) env->NewGlobalRef(cls);
env->DeleteLocalRef(cls);
jmd = env->GetStaticMethodID(globalClass, "getTestFromJava",
"()Ljava/lang/String;");
LOGE(" Method -------------------");
}
jstring job = (jstring) env->CallStaticObjectMethod(globalClass, jmd);
return job;
}
GetObjectClassのclassをグローバル変数として作成し、クラスを作成するたびにglobalClass=(jclass)env->NewGlobalRef(cls)を最適化します.
テスト結果:JNIが計算した200000文字列の読み出し時間差:4742
関連資料:JNIグローバルローカル変数、強弱引用