|
Usage
How to use the profiling library
Featured Build ChangesPlace the libandprof.a static library in the same place as your build. cd $HOME/path/to/my-project unzip android-ndk-profiler.zip This will extract the files prof.h, and 2 versions of libandprof.a - one for armeabi and one for armeabi-v7a. The NDK build system uses the TARGET_ARCH_ABI variable to select which version of the library to use. Modify your Android.mk to include the provided Make snippet, add the libandprof.a static library and compile your code with profiling information. # include the profiler snippet -include android-ndk-profiler.mk # this is your shared library include $(CLEAR_VARS) # compile with profiling LOCAL_CFLAGS := -pg LOCAL_STATIC_LIBRARIES := andprof # android logging library is required for the profiler LOCAL_LDLIBS += -llog # ... your build ... include $(BUILD_SHARED_LIBRARY) The above requires NDK r5b or later, as previous versions did not support pre-built 3rd party libraries. If you can only use r4b, then you will need to include the android-ndk-profiler source code in your build as a static library. If you do this, then make sure not to compile the profiling code with profiling options (-pg). Code ChangesAdd calls to monstartup and moncleanup to your start and shutdown functions. /* in the start-up code */
monstartup("your_lib.so");
/* in the onPause or shutdown code */
moncleanup();The monstartup call expects the name of your library. It needs this to find out what the real addresses are of the functions in the library, since Linux uses ASLR to change the function addresses for added security. Add write permissions to the AndroidManifest.xml file, so your application may write to the sdcard. The gmon.out file is saved in /sdcard/gmon.out. These are the lines to add to AndroidManifest.xml <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> If you do not want to modify the AndroidManifest.xml file to add write permissions, you can save gmon.out to a file in your application's private storage area. To do this, set the environment variable CPUPROFILE to the gmon.out file name any time before calling the moncleanup function: setenv("CPUPROFILE", "/data/data/com.example.application/files/gmon.out", 1);
moncleanup();Things to note:
ExecutionOnce you have made the modifications above you can compile and run your application. Run your code, profile it, then do something to trigger the moncleanup() call. This will create or overwrite /sdcard/gmon.out on the Android device or emulator. You shouldn't call moncleanup() nor monstartup() more than once. Back on your PC, pull the gmon.out file from your Android device or emulator adb pull /sdcard/gmon.out . Run the gprof tool, passing it the non-stripped library (usually in $PROJECT/obj/local/armeabi-v7a/libXXXX.so or $PROJECT/obj/local/armeabi/libXXXX.so). This is for NDK version r5b onwards, in earlier versions the path to gprof is different but should still work. $ANDROID_NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gprof your_lib.so The output is the profile information. To interpret this data you may like to take a look at this guide. There's a slight bug in version 3 where the profiling functions will appear in the timing information. To ignore these and get just your code's information, use the -P and -Q options to gprof like this: arm-linux-androideabi-gprof your_lib.so \
-PprofCount -QprofCount -P__gnu_mcount_nc -Q__gnu_mcount_ncEnvironment VariablesThe profiling library will read the following environment variables: CPUPROFILEThis is the path to the gmon.out file that is generated when your code calls moncleanup. To change the location, set the variable any time before calling moncleanup. Example: setenv("CPUPROFILE", "/data/data/com.example.application/files/gmon.out", 1);CPUPROFILE_FREQUENCYThis controls how many interrupts per second the profiler samples. The default is 100 per second. Set this variable before calling the monstartup function. Example: setenv("CPUPROFILE_FREQUENCY", "500", 1); /* Change to 500 interrupts per second */
monstartup("your_lib.so");Solving ProblemsIf you have problems, check the logcat output and grep for PROFILING. Possible problems are being unable to write to the sdcard or unexpected infinite recursion while profiling. |