Kito's Lab

Monday, January 14, 2013

I am glad to introduce our new tool, Aprof : an Android profiler, it's
a profiling tool for Android native code; aprof is not only another
gprof implement on Android but also support for profiling shared
library. The most important thing is that aport supports the profiling
for JNI code!

The capability of aprof is similar to what gprof does, it provides
call graph and time sampling profiling, but it's incompatible with
gprof since the gprof can't profile shared library, it's limited by
its representation.

Usage for aprof

If you want to profile an executable or static library, you can turn
on aprof by inserting the following line to Android.mk:

LOCAL_ENABLE_APROF := true

There are two modes for profile shared library. The first one is
specify for Non-JNI used shared library, it's just used like
executable, but it only triggers aprof when the executable is being
profiled.

The second mode is designed for JNI, it's called JNI mode, it's
life-cycle-sensitive for Activity : active when onStart, stop and dump
profiling when onStop; but here is one exception in JNI mode, it will
trade as Non-JNI mode if the shared library are opened by the
executable which is already turn on the aprof, So you can turn-on JNI
mode aprof for shared library by adding the follow line to Android.mk:

LOCAL_ENABLE_APROF_JNI := true

In addition, regarding JNI-mode is you should make sure your
application have the permission to write external storage. Here is the
setting example in the AndroidManifest.xml.

You can start profiling your program after recompiling executables
with aprof and execute on the Android device, After the profiling has
been accomplished, the result will be put in the /mnt/sdcard/
(according `EXTERNAL_STORAGE` environment variable), the default file
name is executable name with .aprof suffix : $(progname).aprof And the
next step is grabbing the data to the host, you can grab by adb

self ms/call : the average number of milliseconds spent in this
function per call.

total ms/call :the average number of milliseconds spent in function
and its descendants per call

And the lower part shows the detail for each function.

We can see a unusual symbol in the above example output, the
reason is that aprof don't load the symbol information of the shared
libraries, we can specify the search path for shared libraries by -L
option. In general, we can set the searching path to the
out/target/product/*/symbols/system/lib.

# aprof $(prog_file) $(prof_file) -L$(lib_path)

aprof foo foo.aprof -L out/target/product/panda/symbols/system/lib
We will get more details of profiling data after loading symbol, but
it still imprecise info in the output since the shared libraries
building without aprof, so the part of `calls` and `cumulative time`
may be incorrect; however the `Self time` can show after we load the
symbol info.

And the last part is about visualization part of aprof, aprof supports
the `dot` format by `-d` option, so we can use the `dot`(usually in
graphviz package) program to output the call graph with timing info by
the pipeline, you can reference the following command :