Android 有提供java level的profiler
詳情請看
http://developer.android.com/tools/debugging/debugging-tracing.html
使用方法很簡單, 開始跟結束加上以下的程式, 就會在/sdcard/
.trace, 可以用adb pull /sdcard/.trace 把檔案取出來~ 接著就可以用traceview打開
// start tracing to "/sdcard/calc.trace"
Debug.startMethodTracing("");
// ...
// stop tracing
Debug.stopMethodTracing();
但是沒辦法看到native code (JNI)以下的部分, 我測試了
android-ndk-profiler, 按照說明的方式修改你的Android.mk, 然後把下載後的android-ndk-profiler 放到你的$NDK_MODULE_PATH 下面, 記得要profiling的library都要加上-pg 來compile
# add at beginning
LOCAL_CFLAGS := -pg
LOCAL_STATIC_LIBRARIES := android-ndk-profiler
# at the end of Android.mk
$(call import-module,android-ndk-profiler)
接著在你想要開始跟結束的地方加上profiling method, 跑完就會產生/sdcard/gmon.out.
/* in the start-up code */
monstartup("your_lib.so");
/* in the onPause or shutdown code */
moncleanup();
接著就可以用gprof 解開檔案
# find gprof under android sdk folder
$ find $ANDROID_NDK | grep gprof
# put gmon.out under your project top folder
$ $ANDROID_NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin/arm-linux-androideabi-gprof obj/local/armeabi-v7/your_lib.so > a.log
$ cat a.log
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
17.46 9.07 9.07 S32_opaque_D32_filter_DX(SkBitmapProcState const&, unsigned int const*, int, unsigned int*)
8.86 13.67 4.60 boxBlurInterp(unsigned char const*, int, unsigned char*, int, int, int, bool, unsigned char)
7.37 17.50 3.83 S32A_Opaque_BlitRow32_arm(unsigned int*, unsigned int const*, int, unsigned int)
7.32 21.30 3.80 D32_A8_Color(void*, unsigned int, void const*, unsigned int, unsigned int, int, int)
3.60 23.17 1.87 arm_memset32
2.89 24.67 1.50 RepeatX_RepeatY_filter_scale(SkBitmapProcState const&, unsigned int*, int, int, int)
1.66 25.53 0.86 __gnu_mcount_nc
1.46 26.29 0.76 S32A_Blend_BlitRow32_arm(unsigned int*, unsigned int const*, int, unsigned int)
1.08 26.85 0.56 D32_A8_Opaque(void*, unsigned int, void const*, unsigned int, unsigned int, int, int)
1.06 27.40 0.55 profCount
....
android-ndk-profiler
原理, 其實就是利用compiler -pg 會插入__gnu_mcount_nc method, 所以他就去implemnent __gnu_mcount_nc 來對method invoke 計數~
經過
fcamel 提醒, 這類安插code進去的profiling 是屬於Instrumentation (有可能影響程式流程), 像是我用android-ndk-profiler 有些static library 就不能加-pg, 不然程式會hang住, 另外像是oprofile 則是sampling的方式, 透過CPU interrupt 去sample (比較不會影響程式進行), 不過目前我沒有找到其他方式來做native code profiling ...
Profiler wiki