2014年1月27日 星期一

[Android] CPU profiler

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

沒有留言:

張貼留言