一、概述
Android NDK Profile工具用于在手机上对C/C++代码进行Profile,统计出各个函数的耗时及其比例,进而有针对性的对耗时比例大的函数进行优化。Android NDK Profile Usage网站http://code.google.com/p/android-ndk-profiler/wiki/Usage,介绍了该工具的用法。
注意:
该工具仅用于Profile,测试各函数耗时比例,一旦优化完成后,要将添加至的.mk文件中内容以及添加至C/C++代码中内容去掉,否则严重影响性能。
二、在Android工程中的AndroidManifest.xml添加SDcard写入权限
由于该工具将profile信息写至SDcard文件中,需要SDcard写入权限。现在大多数工程都添加了SDcard写入权限,如果工程中没有添加此权限,需在AndroidManifest.xml中添加如下代码,以添加SDcard写入权限。
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
三、下载Android NDK Profiler native module
网址一: https://github.com/cinar/android-ndk-profiler/zipball/master,该网址目前公司网络不能连接;
网址二: http://code.google.com/p/android-ndk-profiler/downloads/list,该网址经测试可以连接,如图1所示,选择android-ndk-profiler-v3.2.zip,目前这个版本是最新的,如果有更新的可以下载最新版。
图1 android-ndk-profiler文件
四、解压上步下载的压缩包至指定路径
解压android-ndk-profiler-v3.2.zip至F:\Android\android-ndk-r8b\sources目录下,该目录记为PATH_1便于后续描述,该文件解压至任意位置均可(路径中不要包含中文),但是一般解压至Android NDK目录下的sources目录下,解压后的文件目录如图2所示,其中包含prof.h,该文件第七步中需要,注意图2中红框中的目录层级。
图2 android-ndk-profiler文件目录
五、修改Cygwin的.bash_profile文件
找到Cygwin的安装目录下home/<用户名(一般是samsung)>/.bash_profile文件,用UltraEdit打开,用记事本等的打开会出问题,不要转换格式,否则出问题。在安装完Cygwin曾经对该文件进行过修改,当时是添加ANDROID_NDK_ROOT,此处需要进一步添加NDK_MODULE_PATH,如下所示,其中红色字体是本次要添加部分,黑色字体是安装完Cygwin后添加的,注意路径,其中的/F/Android/android-ndk-r8b/sources即为PATH_1;
ANDROID_NDK_ROOT=/cygdrive/F/Android/android-ndk-r8b
export ANDROID_NDK_ROOT
NDK_MODULE_PATH=/cygdrive/F/Android/android-ndk-r8b/sources
export NDK_MODULE_PATH
六、修改Android.mk文件
注意NDK的版本,要使用r5b或之后的版本,我们目前大多使用的是r8b,满足这个要求。以一个mk文件为例进行说明:
图3 Android.mk文件
如图3所示,在Android.mk文件中添加两部分内容(如图3中第2、4红框所示);
注意:
1)第3个红框为原始Android.mk的内容,其必须位于第2、4红框中间;
2)第1个红框为module名,第七步中需要。
七、修改C/C++文件
首先在需要进行profile的文件中添加头文件prof.h(见图2),需要将该文件复制至当前jni目录下,否则找不到文件。以修改native.cpp文件为例进行说明。
#include <prof.h> //在文件中添加prof.h头文件
在需要进行profile的函数部分,按如下格式添加语句;
// Start collecting the samples
setenv("CPUPROFILE_FREQUENCY","200", 1); /* Change to 200 interrupts per second */
monstartup("libFaceDetect.so"); //开始进行profile
caFace_FDRunOrigin((unsignedchar*)pImage, OrgWidth, OrgHeight);//facedetectoion
nDetectFace = caFace_getFaceNum();
for(int i=0;i<nDetectFace;i++)
caFace_EDRun((unsignedchar*)pImage,OrgWidth,OrgHeight,i); // eye detection
// Store the collected data
moncleanup(); //结束profile
说明:
1) monstartup("libFaceDetect.so");开始进行profile,其中的libFaceDetect.so即为图3第1个红框所示的module名。
2) moncleanup();结束profile,保存profile数据。
3) 两者中间部分即为profile的对象。
4) setenv("CPUPROFILE_FREQUENCY", "200", 1); /* Change to 200 interrupts per second */
该语句用于设置profile的采样频率,默认为100次/秒。上述语句设置为200次/秒,根据profile部分耗时的多少进行设定,采样频率设置过大过小均影响准确度,在测试中耗时为110ms左右,采样频率设定为200次/秒,根据实际耗时的大小进行相应的调整。耗时多则降低采样频率,耗时少则增大采样频率。
八、导出profile过程中生成的gmon.out
Profile过程中生成的gmon.out文件路径为/sdcard/gmon.out,即存放在SDcard的根目录下,三种方式可以导出该文件:
1) 命令行输入如下命令,注意适当变更红色字体部分的路径,将该文件保存到F:\目录下,如图4所示;
F:\Android\android-sdk-windows\platform-tools\adb.exe pull /sdcard/gmon.out F:\
图4 使用命令行导出gmon.out
2) 使用Eclipse集成开发环境中DDMS导出gmon.out文件,如图5所示,注意:在DDMS中sdcard是挂载在/mnt下面,如图5中红框所示,选中/mnt/sdcard/gmon.out文件,然后点击图5中箭头所指的按钮即可导出文件至PC中。
图5 使用DDMS导出gmon.out文件
3) 使用USB数据线,以U盘模式导出gmon.out文件,此为常规的文件拷贝,不在赘述。
九、生成Profiler Report File
命令行中输入如下命令:
F:\Android\android-ndk-r8b\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin\arm-linux-androideabi-gprof.exe F:\Android\workspace\FaceEyeDetectKHQ\obj\local\armeabi-v7a\libFaceDetect.so F:\gmon.out
说明:
1) 蓝色字体部分为android-ndk中的一个工具,根据NDK存放路径参考上面路径进行查找。
2) 红色字体部分为生成的libFaceDetect.so库,一般在Android工程中的obj\local\armeabi-v7a\目录下。
3) 绿色字体部分即为步骤六中导出的文件。
运行上述命令后的结果,如图6所示,每列的含义见下面说明部分。
图6 Profile Report
十、八九两步合并至批处理文件
此步为八、九两步的合并,将两步的命令写至一个批处理文件中,写该批处理文件只是为了方便,如果八、九两步已做完,可忽略此步。
文件内容如图7所示;
图7 GenAndroidProfileReport.bat文件
文件内容如下,进行简要说明:
F:\Android\android-sdk-windows\platform-tools\adb.exe pull /sdcard/gmon.out F:\
F:\Android\android-ndk-r8b\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin\arm-linux-androideabi-gprof.exe F:\Android\workspace\FaceEyeDetectKHQ\obj\local\armeabi-v7a\libFaceDetect.so F:\gmon.out
上面文字中的红色字体部分根据实际情况对路径进行相应的修改。