发布时间:Dec. 20, 2022, 11:16 a.m.编辑:李佳生阅读(3817)
分析整个安卓apk的函数热点,分析函数的cpu消耗,进行cpu优化。
Android手机: 需要root
adb环境安装: brew install --cask android-platform-tools
simpleperf可执行文件: 一般随NDK安装
一般simpleperf会随NDK安装在NDK目录下:
cd ~/Library/Android/sdk/ndk/21.0.6113669/simpleperf/bin/android/arm64
拷贝simpleperf到安卓机器:
adb push simpleperf /data/local/tmp
获取应用程序的pid
adb shell top
adb shell am start -n 包名/启动程序
adb shell pidof 包名
adb shell // 进入adb终端模式 cd /data/local/tmp // simpleperf所在目录 su // root手机、切换管理员权限 // stat命令获取一段时间内已分析进程中发生的事件数摘要。 ./simpleperf stat [options] [command [command-args]] // 常用 ./simpleperf stat -p 进程号 --duration 检测进程的持续时间(秒) // record命令记录一段时间内已分析进程的样本,是simpleperf的主命令。 ./simpleperf record [options] [command [command-args]] // 常用 ./simpleperf record -p 进程号 -o 输出文件(默认perf.data) --duration 监测时间(秒) // 例子./simpleperf record -p 4201 -e task-clock -g --duration 20// report命令读取perf.data文件(simpleperf record创建)并显示报告。 ./simpleperf report [options] // 常用 ./simpleperf report --dsos 选定动态共享对象(so库) -f 记录文件(默认perf.data) --sort 用于排序和打印报告的键 -n // 若出现Access to kernel symbol addresses is restricted警告,可使用命令取消: echo 0>/proc/sys/kernel/kptr_restrict
注意事项:
Simpleperf支持两种方式记录方法调用信息,一种基于DWARF(record --call-graph dwarf or record -g),另一种基于帧指针(record --call-graph fp).
通常使用--call-graph fp比--call-graph dwarf速度更快,如果你的Android设备是AArch-64架构(arm64-v6a)应该使用--call-graph fp,在ARM架构(armeabi或者armeabi-v7a)的设备上不能用--call-graph fp,这是因为ARM架构的设备上通常没有帧指针寄存器。
在ARM架构的设备上应该使用--call-graph dwarf,在这种方式下,Simpleperf使用libunwind解析栈信息。为了使用--call-graph dwarf,我们必须提供带有调试信息的native库,基于此建议在APK中构建带有调试信息的native库。
把.data文件adb pull到report生成脚本所在目录: 一般为simpleperf根目录
// exit指令退出adb shell环境, 执行: adb pull /data/local/tmp/perf.data ./ // cd 到report_html.py所在目录,执行: python3 report_html.py -i 文件名 // 默认输入文件为perf.data
生成的html文件包括三部分: 饼状图、表格、火焰图
饼状图效果如下: 显示了各个任务CPU占比,并且可以点击各部分,生成这部分的子任务饼状图
表格: 内容与饼状图一致,以表格形式展现
火焰图: 从下到上是调用栈,颜色越深表示cpu消耗越大,具体消耗可以在上面的文本框中显示。
当前报告生成脚本使用的库不支持arm64,因此使用M1芯片的电脑无法执行脚本。
解决方法1:
https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/android_platform_profiling.md
解决方法2:
修改build.gradle.kts,增加配置,避免库文件编译的时候符号表被strip:
packagingOptions { ... doNotStrip("*/arm64-v8a/*.so") doNotStrip("*/armeabi/*.so") doNotStrip("*/armeabi-v7a/*.so") doNotStrip("*/x86/*.so") }
然后就可以看到具体的函数名了:
上一篇:Git使用教程
下一篇:耳机ANC主动降噪算法简介