寫一寫前兩天用android ndk profiler 分析本地代碼的過程,在此記錄一下,防止之後忘記 步驟:html
一、官網下載android ndk profile :https://code.google.com/p/android-ndk-profilerjava
二、更改Android.mk, 加載android ndk profiler模塊。 其實這個步驟的詳細過程官網已經有了,基本按官網的說明來作就能夠了:http://code.google.com/p/android-ndk-profiler/wiki/Usagelinux
<!-- lang: shell --> # compile with profiling LOCAL_CFLAGS := -pg LOCAL_STATIC_LIBRARIES := android-ndk-profiler # at the end of Android.mk $(call import-module,android-ndk-profiler)
看個人android.mk:android
<!-- lang: shell --> LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # compile with profiling LOCAL_CFLAGS := -pg LOCAL_STATIC_LIBRARIES := android-ndk-profiler LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY) # at the end of Android.mk $(call import-module,android-ndk-profiler)
三、3 在啓動和結束函數裏,加入監視代碼。默認會產生sdcard/gmon.out文件。因此你須要在sdcard上的寫權限,修改AndroidManifest.xml,加上:shell
<!-- lang: java --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
四、修改本地代碼,在本地代碼須要調試的起始位置和結束位置加上監視函數:ubuntu
<!-- lang: cpp --> /* in the start-up code */ monstartup("your_lib.so"); /* in the onPause or shutdown code */ moncleanup();
個人例子的代碼:ide
<!-- lang: cpp --> #include<string.h> #include<stdio.h> #include<math.h> #include <memory.h> #include<jni.h> jstring Java_com_wxg_ndkdemo_MainActivity_stringFromJNI(JNIEnv *env ,jobject thiz) { int i ; setenv("CPUPROFILE_FREQUENCY", "500", 1); /* Change to 500 interrupts per second */ monstartup("libhello-jni.so"); test(); // setenv("CPUPROFILE", "/sdcard/gmon.out", 1); moncleanup(); return (*env)->NewStringUTF(env,"Hello from JNI !"); } jint add() { int i=10000,j=0; for(i=0;i<10000;i++) { for(j=0;j<10000;j++) { i*j; } } return i+j; } jint test() { add(); // int i; // char buffer[] = "Hello world/n"; // printf("Buffer before memset: %s/n", buffer); // memset(buffer, '*', strlen(buffer) ); // printf("Buffer after memset: %s/n", buffer); // // FILE *fp = fopen("/sdcard/a.txt","at"); // // fprintf(fp,"%s\n",buffer); // // for(i=0;i<100000;i++) // { // char ch[30]; // sprintf(ch,"the number is %d\n",i); // char str[30]; // memcpy(str,ch,strlen(ch)); // fputs(ch,fp); //// fprintf(fp,"%s\n",ch); // } // // fclose(fp); int i,j; double s = 0,temp=1.0; for(i=1;i<=5000000;i++) { s += sqrt(temp); temp = s; } return 0; }
五、使用ndk-build編譯本地代碼函數
<!-- lang: shell --> ubuntu@ubuntu:~/workspace/NDKDemo$ ndk-build NDK_MODULE_PATH=~/android/ Install : libhello-jni.so => libs/armeabi/libhello-jni.so
其中ui
<!-- lang: shell --> NDK_MODULE_PATH=~/android/
指向的是包含android_ndk_profiler文件夾的目錄,看個人google
<!-- lang: shell --> ubuntu@ubuntu:~/android$ ls android-ndk* android-ndk-profiler: Android.mk armeabi armeabi-v7a prof.h android-ndk-r8e: build documentation.html ndk-build ndk-gdb ndk-gdb.py ndk-stack platforms README.TXT samples tests docs GNUmakefile ndk-build.cmd ndk-gdb-py ndk-gdb-py.cmd ndk-which prebuilt RELEASE.TXT sources toolchains
六、運行程序,最後查看結果
使用gprof命令產生結果,須要先用adb pull命令將gmon.out文件拷貝到本身的PC上
先進入你android的NDK項目的obj目錄下的objs下的子目錄下:
<!-- lang: shell --> ubuntu@ubuntu:~/workspace/NDKDemo/obj/local/armeabi/objs/hello-jni$ ls hello-jni.o hello-jni.o.d ubuntu@ubuntu:~/workspace/NDKDemo/obj/local/armeabi/objs/hello-jni$ adb pull /sdcard/gmon.out 355 KB/s (16463 bytes in 0.045s) ubuntu@ubuntu:~/workspace/NDKDemo/obj/local/armeabi/objs/hello-jni$ ls gmon.out hello-jni.o hello-jni.o.d
最後使用NDK的gprof查看結果
<!-- lang: shell --> ubuntu@ubuntu:~/workspace/NDKDemo/obj/local/armeabi/objs/hello-jni$ ~/android/android-ndk-r8e/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gprof hello-jni.o