惠阳住房和建设局网站,aspx网站架设教程,网站通栏尺寸,泉州北京网站建设价格一、Simpleperf介绍
Simpleperf是一个强大的命令行工具#xff0c;它包含在NDK中#xff0c;可以帮助我们分析应用的CPU性能。Simpleperf可以帮助我们找到应用的热点#xff0c;而热点往往与性能问题相关#xff0c;这样我们就可以分析修复热点源。
如果您更喜欢使用命令…
一、Simpleperf介绍
Simpleperf是一个强大的命令行工具它包含在NDK中可以帮助我们分析应用的CPU性能。Simpleperf可以帮助我们找到应用的热点而热点往往与性能问题相关这样我们就可以分析修复热点源。
如果您更喜欢使用命令行可以直接使用 Simpleperf。Simpleperf 是一个通用的命令行 CPU 性能剖析工具包含在面向 Mac、Linux 和 Windows 的 NDK 中。
如需查看完整的文档请先阅读 Simpleperf https://android.googlesource.com/platform/system/extras//master/simpleperf/doc/README.md。
官方的资料
Simpleperf 命令和选项参考Simpleperf 用法
二、基本工作原理
现代 CPU 具有一个硬件组件称为性能监控单元(PMU)。PMU 具有一些硬件计数器计数一些诸如经历了多少次 CPU 周期执行了多少条指令或发生了多少次缓存未命中等事件。
Linux 内核将这些硬件计数器包装到硬件 perf 事件中。此外Linux 内核还提供了独立于硬件的软件事件和跟踪点事件。Linux 内核通过 perf_event_open 系统调用将这些暴露给用户空间这正是 simpleperf 所使用的机制。
Simpleperf 具有三个主要的功能statrecord 和 report。
Stat 命令给出了在一段时间内被剖析的进程中发生了多少事件的摘要。以下是它的工作原理
给定用户选项simpleperf 通过对 linux 内核执行系统调用来启用剖析。Linux 内核在调度到被剖析进程时启用计数器。剖析之后simpleperf 从内核读取计数器并报告计数器摘要。
Record 命令记录一段时间内被剖析进程的采样。它的工作原理如下
给定用户选项simpleperf 通过对 linux 内核执行系统调用来启用剖析。Simpleperf 在 simpleperf 和 linux 内核之间创建映射缓冲区。Linux 内核在调度到被剖析进程时启用计数器。每次给定数量的事件发生时linux 内核将样本转储到映射缓冲区。Simpleperf 从映射缓冲区读取样本并stat生成 perf.data。
Report 命令读取 “perf.data” 文件及所有被剖析进程用到的共享库并输出一份报告展示时间消耗在了哪里。
三、环境要求
为了使用Simpleperf, 需要以下环境
待分析的App应运行在Android 5.0或者更高版本的设备上手机的USB 连接到操作机器应用程序应该是 debuggable 的。由于安全限制的原因只有 android::debuggable 设置为 true 的应用程序才能剖析。在一个已经 root 的设备上所有应用程序都可以剖析。在 Android Studio 中这意味着我们需要使用 debug 构建类型而不是 release 构建类型。为了能够运行Python scripts宿主机器应安装Python 2.7或者更高版本NDK的版本应不低于r13b
通常剖析 Android 应用程序性能包含三个步骤
准备应用程序。记录剖析数据。生成剖析数据的分析报告。Simpleperf的获取路径https://android.googlesource.com/platform/prebuilts/simpleperf/
在页面内可以直接压缩包下载既可以选择NDK相对应的版本(R13~N21)也可以选择master。建议直接选择NDK对应的版本即可。当然也可以git直接拉取仓库。
git clone https://android.googlesource.com/platform/prebuilts/simpleperf
查看下载的simpleperf目录可以看出它的工具集包涵client端和host端client端运行在Android系统上负责收集性能数据host端则运行在开发机上负责对数据进行分析和可视化(这些可执行文件在下载后的bin文件夹的android和win/linux下)。
除了bin文件夹之外最上层还有很多.py的脚本文件。这些脚本和配置文件主要是官方写的一些傻瓜式的使用脚本只需要对配置文件进行配置就可以在直接在开发机上直接运行脚本一键生成最终的结果。
Python 脚本根据它们的功能被分为三个部分
用于简化剖析数据记录的脚本如 app_profiler.py。用于生成剖析报告的脚本如 report.pyreport_html.pyinferno。用于解析剖析数据的脚本如 simpleperf_report_lib.py。
主要的脚本是app_profiler.py和report.py两个。
在android-ndk\simpleperf中包含了 simpleperf 可执行文件和 Python 脚本它们的功能如下
bin/包含可执行文件及共享库里面包含了android和windows。bin/android/${arch}/simpleperf设备上运行的静态 simpleperf 可执行文件。其中 ${arch} 为目标设备的 CPU 架构如 arm 和 arm64。bin/${host}/${arch}/simpleperf用于主机的 simpleperf 可执行文件只支持生成报告。其中 ${host} 为主机的操作系统平台如 linux${arch} 为主机的 CPU 架构如 x86_64。bin/${host}/${arch}/libsimpleperf_report.${so/dylib/dll}用于主机的报告生成库。其中 ${host} 指主机的操作系统平台${arch} 为主机的 CPU 架构。app_profiler.py用于记录剖析数据的 Python 脚本。binary_cache_builder.py用于为剖析数据构建二进制缓存的 Python 脚本。report.py用于生成剖析报告并输出到标准输出的 Python 脚本。report_html.py用于生成剖析报告并输出为 html 文件的 Python 脚本。inferno.sh 或 Windows 平台的 inferno.bat )用于生成火焰图并输出为 html 文件的脚本工具。inferno/inferno 的实现。由 inferno.sh 使用。pprof_proto_generator.py将剖析数据的格式转换为 pprof 使用的格式的 Python 脚本。report_sample.py将剖析数据的格式转换为 FlameGraph 使用的格式的 Python 脚本。simpleperf_report_lib.py解析剖析数据的库。
脚本的主要内容就是读取配置文件然后执行adb shell ...的命令其实本质上和命令行的输入没什么区别。但是如果直接运行不仅仅需要查看配置文件各个配置项的含义还可能会出现许多意想不到的BUG不太建议直接使用脚本不得精髓啊。
四、支持的命令
debug-unwind命令基于debug / test dwarf的离线展开用于调试simpleperf。
dump命令转储perf.data中的内容用于调试simpleperf。
help命令打印其他命令的帮助信息。
kmem命令收集内核内存分配信息将被Python脚本替换。
list命令列出Android设备支持的所有事件类型。
记录命令配置文件处理并在perf.data中存储分析数据。
report命令报告perf.data中的分析数据。
report-sample命令报告perf.data中的每个样本用于支持集成Android Studio中的simpleperf。
stat命令profiles处理并打印计数器摘要。
每个命令都支持不同的选项可以通过帮助消息查看如下示例
# List all commands.
$ simpleperf --help
# Print help message for record command.
$ simpleperf record --help
五、操作流程
方式一使用adb shell进入手机页面操作
1、将simpleperf文件push到手机
在simpleperf/bin/android目录下包含有不同体系架构的 Android 上运行的静态二进制文件在arm目录下打开命令窗口执行命令
adb push simpleperf data/data/
2、将simpleperf授权为可读可写可执行文件
adb shell
cd data/data/
chmod 777 simpleperf
3、对某些特定进程或者线程监控
./simpleperf record -p 4281(pid 或tid) --duration 30(时间/s)
得到错误提示说只读分区无法写入 perf.data:
simpleperf E 04-19 15:09:29 4109 4109 record_file_writer.cpp:47] failed to open record file perf.data: Read-only f
4、 用 -o 参数设置存储记录的路径
simpleperf I cmd_record.cpp:729] Recorded for 29.9851 seconds. Start post processing.
simpleperf I cmd_record.cpp:809] Samples recorded: 1457. Samples lost: 0.
5、用report 报告perf.data中的分析数据
simpleperf record -p 17465--duration 4 -f 1000 -o /data/local/tmp/perf.data --call-graph fp
simpleperf report -i /data/perf.data -n --sort dso
simpleperf W 04-19 15:31:17 4564 4564 dso.cpp:274] /data/local/rvdecApp doesnt contain symbol table
simpleperf W 04-19 15:31:17 4564 4564 dso.cpp:335] Symbol addresses in /proc/kallsyms are all zero. echo 0 /proc/sys/kernel/kptr_restrict if possible.
Cmdline: /data/local/tmp/simpleperf record -p 4281 --duration 30 -o /data/perf.data
Arch: arm64
Event: cpu-cycles (type 0, config 0)
Samples: 125526
Event count: 43633757353Overhead Sample Shared Object
88.93% 106529 /data/local/rvdecApp
8.05% 10560 /system/lib/libc.so
3.01% 8437 [kernel.kallsyms]
其中的 –sort 参数是用来指定结果显示哪些列我们这里只写了一个 dso即 dynamic shared object所以结果只显示一列 “Shared Object”而且按 dso 分类结果也只有三行而已。
如果不加 –sort 参数默认显示这几列CommandPidTidShared ObjectSymbol相当于
--sort comm,pid,tid,dso,symbol
-n 参数用来显示 Sample 那列表示该行共命中了多少个 Sample加不加随意。可以看到百分之 88.93 的时间都耗费在了我们的被测程序上这是预期中的。
6、查看app 内部函数占比
simpleperf report -i /data/perf.data --dsos /data/local/rvdecApp --sort symbol
结果如下
impleperf W 04-19 15:57:34 5046 5046 dso.cpp:274] /data/local/rvdecApp doesnt contain symbol table
simpleperf W 04-19 15:57:34 5046 5046 dso.cpp:335] Symbol addresses in /proc/kallsyms are all zero. echo 0 /proc/sys/kernel/kptr_restrict if possible.
Cmdline: /data/local/tmp/simpleperf record -p 4281 --duration 30 -o /sdcard/perf.data
Arch: arm64
Event: cpu-cycles (type 0, config 0)
Samples: 106529
Event count: 38804869540Overhead Sample Symbol
5.06% 5373 rvdecApp[24380]
4.57% 4890 rvdecApp[24420]
1.43% 1588 rvdecApp[13a44]
1.01% 1083 rvdecApp[21f94]
0.94% 999 rvdecApp[20188]
...
其中的 –dsos 参数是 simpleperf 的 5 个 filter 之一意思是按照指定的 dynamic shared objects 进行过滤只显示参数指定的 dso 里面的结果。全部 5 个 filter 是
–comms 按 command 过滤比如--comm rvdecApp
–pids: 按 pid 过来
–tids: 按 tid线程id过滤
–dsos 按库文件/可执行文件名过滤
–symbols 按函数名过滤比如 --symbols RVComFunc::getPUMVPredictor(RefBlockInfo*, unsigned int, int, int, unsigned int)注意函数里有空格的需要用双引号引起来。
可以看到结果里没有函数名字。那是因为我们的 rvdecApp 是没有符号表的版本。我们用带符号表的 app 进行分析即可。
带符号表的 app 可执行文件可以在 obj 目录下找到。把它 push 到手机上覆盖原来的可执行文件。
注意不用重新执行 rvdecApp 并重新采集 perf.data, 只需要在分析时使用带有符号表的 rvdecApp 即可。
还用刚才的命令
./simpleperf report -i /data/perf.data -n --dsos /data/local/rvdecApp --sort symbol
得到如下结果
Overhead Sample Symbol
10.45% 5354 RVComFunc::DBFShiftedProcess8x8(unsigned char**, int*, unsigned char*, int, unsigned char*, int, bool, bool, bool, bool, unsigned char)
5.55% 3722 RVComFunc::deblockCUTree(TCBDataTree*, unsigned char**, unsigned int*, int, int, RefBlockInfo*, int, unsigned char**, int*, unsigned char)
4.49% 3675 RVComFunc::reconstructInterPredictors(TCUData*, unsigned char**, unsigned int*, TRefPicList*, RefBlockInfo*, unsigned int, unsigned int, unsigned int, unsigned int)
2.25% 3518 RVComFunc::deriveDBFStrengthFUbyMotionInfo(unsigned char*, unsigned char*, int, int, RefBlockInfo*, int, int, unsigned char, unsigned char, bool, bool)
2.68% 3320 Decoder::parseBitStream_FrameNew()
2.79% 2927 NEON_DBF_EdgeFilter4_Vertical
2.52% 2651 RVComFunc::DBFShiftedProcessFu(unsigned char**, int*, unsigned char*, int, unsigned char*, int, int, bool, bool, bool, bool, unsigned char)
2.36% 2553 (anonymous namespace)::decode_gen_vlc(unsigned long const*, int, (anonymous namespace)::VLC*, int, int)
...
可以看到DBFShiftedProcess8x8函数是最耗时的函数需要被优化。
方式二使用linux环境使用python脚本操作
1、 运行app-profiler.py
进入simpleperf目录下我们可以使用 app-profiler.py 剖析 Android 应用程序。输出路径等可以修改app_profiler.py配置文件
14:47:33,547 [INFO] (app_profiler.py:206) prepare profiling
14:47:33,730 [INFO] (app_profiler.py:208) start profiling
14:47:33,806 [INFO] (app_profiler.py:244) run adb cmd: [adb, shell, /data/local/tmp/simpleperf, record, -o, /data/local/tmp/perf.data, -e task-clock:u -f 1000 -g --duration 10, --log, info, --app, com.afmobi.boomplayer]
simpleperf I cmd_record.cpp:696] Recorded for 9.96625 seconds. Start post processing.
simpleperf W dso.cpp:446] /vendor/lib64/egl/libGLES_mali.so doesnt contain symbol table
simpleperf W dso.cpp:446] /vendor/lib64/hw/android.hardware.graphics.mapper4.0-impl-mediatek.so doesnt contain symbol table
simpleperf W dso.cpp:446] /data/app/~~EKnZoTKaDLH3FYfxteqUvg/com.google.android.trichromelibrary_541411734-ozjH9V7NI4SknoCd0t2CPg/base.apk!/lib/arm64-v8a/libmonochrome_64.so doesnt contain symbol table
simpleperf W dso.cpp:446] /data/app/~~3WfX5_4-OAPL17xSEBkRfg/com.afmobi.boomplayer-yFLZq2TqjDUJV1OB-um-UQ/lib/arm64/libmmkv.so doesnt contain symbol table
simpleperf I cmd_record.cpp:771] Samples recorded: 8647. Samples lost: 0.
14:47:45,689 [INFO] (app_profiler.py:211) collect profiling data
14:47:46,745 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\apex\com.android.runtime\lib64\bionic\libc.so
14:47:46,770 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\vendor\lib64\libged.so
14:47:46,800 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\vendor\lib64\egl\libGLES_mali.so
14:47:46,835 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\libEGL.so
14:47:46,867 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\libhwui.so
14:47:46,888 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\libutils.so
14:47:46,913 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\libgui.so
14:47:46,932 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\libnativewindow.so
14:47:46,992 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\framework\arm64\boot-framework.oat
14:47:47,069 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\apex\com.android.art\lib64\libart.so
14:47:47,130 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\framework\arm64\boot.oat
14:47:47,159 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\libandroid_runtime.so
14:47:47,179 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\bin\app_process64
14:47:47,206 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\apex\com.android.vndk.v31\lib64\libhidlbase.so
14:47:47,230 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\libhidlbase.so
14:47:47,260 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\android.hardware.graphics.mapper4.0.so
14:47:47,301 [INFO] (binary_cache_builder.py:184) use current file in binary_cache: binary_cache\system\lib64\libui.so2、运行 report.py脚本 剖析报告并输出
simpleperf W dso.cpp:448] failed to read symbols from /data/app/~~3WfX5_4-OAPL17xSEBkRfg/com.afmobi.boomplayer-yFLZq2TqjDUJV1OB-um-UQ/lib/arm64/libmmkv.so: File not found
Cmdline: /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data -e task-clock:u -f 1000 -g --duration 10 --app com.afmobi.boomplayer
Arch: arm64
Event: task-clock:u (type 1, config 1)
Samples: 8647
Event count: 8647000000Overhead Shared Object Pid
27.69% /system/lib64/libhwui.so 31183
17.32% /apex/com.android.art/lib64/libart.so 31183
9.06% /apex/com.android.runtime/lib64/bionic/libc.so 31183
8.60% /vendor/lib64/egl/libGLES_mali.so 31183
8.50% /system/framework/arm64/boot-framework.oat 31183
4.75% /data/app/~~3WfX5_4-OAPL17xSEBkRfg/com.afmobi.boomplayer-yFLZq2TqjDUJV1OB-um-UQ/oat/arm64/base.odex 31183
3.05% /system/framework/arm64/boot.oat 31183
2.67% /system/lib64/libandroidfw.so 31183
2.58% [JIT app cache] 31183
1.78% /system/lib64/libgui.so 31183
1.58% /data/app/~~EKnZoTKaDLH3FYfxteqUvg/com.google.android.trichromelibrary_541411734-ozjH9V7NI4SknoCd0t2CPg/base.apk!/lib/arm64-v8a/libmonochrome_64.so 31183
1.02% /system/lib64/libbinder.so 31183
0.75% /apex/com.android.art/lib64/libart-compiler.so 31183
0.74% /system/lib64/libminikin.so 31183
0.73% /system/lib64/libz.so 31183
0.68% /system/lib64/libsqlite.so 31183
0.65% /system/lib64/libutils.so 31183
0.64% /system/lib64/libjpeg.so 31183
0.53% /apex/com.android.conscrypt/lib64/libcrypto.so 31183
0.43% /apex/com.android.i18n/lib64/libicuuc.so 31183
0.39% /apex/com.android.runtime/bin/linker64 31183
0.39% /system/framework/arm64/boot-core-libart.oat 31183
0.36% /system/lib64/libc.so 31183
0.27% /system/lib64/libandroid_runtime.so 31183
0.25% /system/framework/arm64/boot-okhttp.oat 31183
0.24% [vdso] 31183
0.22% /apex/com.android.conscrypt/lib64/libssl.so 31183
0.21% /system/lib64/libcutils.so 31183
0.21% /system/lib64/libui.so 31183
0.19% /apex/com.android.vndk.v31/lib64/libgralloctypes.so 31183
.....
3、 产生调用图的报告并输出至标准输出
Cmdline: /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data -e task-clock:u -f 1000 -g --duration 10 --app com.afmobi.boomplayer
Arch: arm64
Event: task-clock:u (type 1, config 1)
Samples: 10841
Event count: 10841000000Children Self Command Pid Tid Shared Object Symbol
66.11% 0.00% RenderThread 31183 11235 /apex/com.android.runtime/lib64/bionic/libc.so __start_thread|-- __start_thread|-- __pthread_start(void*)android::Thread::_threadLoop(void*)android::uirenderer::renderthread::RenderThread::threadLoop()|--0.01%-- [hit in function]||--99.96%-- android::uirenderer::WorkQueue::process()| |--0.03%-- [hit in function]| || |--99.94%-- std::__1::__function::__funcandroid::uirenderer::renderthread::DrawFrameTask::postAndWait()::$_0, std::__1::allocatorandroid::uirenderer::renderthread::DrawFrameTask::postAndWait()::$_0, void ()::operator()() (.c1671e787f244890c877724752face20)| | |--0.01%-- [hit in function]| | || | |--86.61%-- android::uirenderer::renderthread::CanvasContext::draw()| | | |--0.11%-- [hit in function]| | | || | | |--77.75%-- android::uirenderer::skiapipeline::SkiaOpenGLPipeline::draw(android::uirenderer::renderthread::Frame const, SkRect const, SkRect const, android::uirenderer::LightGeometry const, android::uirenderer::LayerUpdateQueue*, android::uirenderer::Rect const, bool, android::uirenderer::LightInfo const, std::__1::vectorandroid::spandroid::uirenderer::RenderNode, std::__1::allocatorandroid::spandroid::uirenderer::RenderNode const, android::uirenderer::FrameInfoVisualizer*)| | | | |--0.08%-- [hit in function]| | | | || | | | |--58.87%-- android::uirenderer::skiapipeline::SkiaPipeline::renderFrame(android::uirenderer::LayerUpdateQueue const, SkRect const, std::__1::vectorandroid::spandroid::uirenderer::RenderNode, std::__1::allocatorandroid::spandroid::uirenderer::RenderNode const, bool, android::uirenderer::Rect const, sk_spSkSurface, SkMatrix const)| | | | | || | | | | |--86.22%-- android::uirenderer::skiapipeline::SkiaPipeline::renderFrameImpl(SkRect const, std::__1::vectorandroid::spandroid::uirenderer::RenderNode, std::__1::allocatorandroid::spandroid::uirenderer::RenderNode const, bool, android::uirenderer::Rect const, SkCanvas*, SkMatrix const)| | | | | | |--0.12%-- [hit in function] 4、 展示火焰图
为了展示火焰图我们首先需要记录调用图。火焰图由 report_html.py 在 Flamegraph 标签中展示。也可以直接双击inferno.bat展示火焰图。
我们也可以使用 GitHub - brendangregg/FlameGraph: Stack trace visualizer 构建火焰图。请确保已经安装了 perl。
$ git clone https://github.com/brendangregg/FlameGraph.git
$ python report_sample.py --symfs binary_cache out.perf
$ FlameGraph/stackcollapse-perf.pl out.perf out.folded
$ FlameGraph/flamegraph.pl out.folded a.svg
用浏览器打开就可以看解析出来的火焰图如下 从上面的火焰图里面就可以看到netd一直在执行什么这样就可以交由netd的同仁继续跟踪
y 轴表示调用栈每一层都是一个函数。调用栈越深火焰就越高顶部就是正在执行的函数下方都是它的父函数。 x 轴表示抽样数如果一个函数在 x 轴占据的宽度越宽就表示它被抽到的次数多即执行的时间长。注意x 轴不代表时间而是所有的调用栈合并后按字母顺序排列的。 火焰图就是看顶层的哪个函数占据的宽度最大。只要有平顶plateaus就表示该函数可能存在性能问题。 颜色没有特殊含义因为火焰图表示的是 CPU 的繁忙程度所以一般选择暖色调。
详细火焰图使用可以参考如何读懂火焰图 - 阮一峰的网络日志
六、提示与诀窍
如果您刚开始使用 Simpleperf不妨试试以下一些特别实用的命令。如需了解更多命令和选项请参阅 Simpleperf 命令和选项参考。
1.查找执行时间最长的共享库
您可以运行此命令来查看哪些 .so 文件占用了最大的执行时间百分比基于 CPU 周期数。启动性能分析会话时首先运行此命令是个不错的选择。
simpleperf report --sort dso
例
Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data
Arch: arm64
Event: cpu-cycles (type 0, config 0)
Samples: 3294
Event count: 1193555038Overhead Sample Shared Object
57.18% 2114 [kernel.kallsyms]
8.01% 225 /system/lib64/libhwui.so
7.16% 192 /apex/com.android.runtime/lib64/bionic/libc.so
5.96% 169 /vendor/lib64/egl/libGLES_mali.so
4.73% 125 /apex/com.android.art/lib64/libart.so
4.55% 128 /system/framework/arm64/boot-framework.oat
3.84% 96 /system/lib64/libgui.so
1.39% 44 /system/framework/arm64/boot.oat
1.06% 28 /system/lib64/libutils.so
0.74% 24 /system/lib64/libbinder.so
0.43% 12 /system/lib64/libui.so
0.42% 10 /system/lib64/libminikin.so
0.34% 10 /system/lib64/libandroid_runtime.so
0.34% 10 /system/lib64/libc.so
0.29% 7 /apex/com.android.vndk.v31/lib64/libgralloctypes.so
0.27% 8 /vendor/lib64/egl/libGLES_meow.so
0.27% 6 /system/framework/arm64/boot-mediatek-framework.oat
0.24% 8 [JIT app cache]
0.22% 7 /system/lib64/libEGL.so
0.19% 5 /vendor/lib64/libged.so
0.19% 6 /apex/com.android.vndk.v31/lib64/libhidlbase.so
0.18% 4 unknown
0.16% 5 /system/lib64/libcutils.so
0.15% 2 /apex/com.android.i18n/lib64/libicuuc.so
0.15% 5 /system/framework/arm64/boot-core-libart.oat
...............
2.查找执行时间最长的函数
当您确定占用最多执行时间的共享库后就可以运行此命令来查看执行该 .so 文件的函数所用时间的百分比。
simpleperf report --dsos library.so --sort symbol
例
simpleperf E command.cpp:59] Unknown option -dsos. Try simpleperf help report.
1|TECNO-KI7:/ # simpleperf report -i /data/perf.data --dsos [kernel.kallsyms] --sort symbol
Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data
Arch: arm64
Event: cpu-cycles (type 0, config 0)
Samples: 2114
Event count: 682442263Overhead Symbol
8.22% _raw_spin_unlock_irqrestore
6.87% __blockdev_direct_IO
6.72% get_user_pages_fast
6.61% dio_bio_complete
4.13% memblock_start_of_DRAM
3.97% el0_da
3.71% blk_queue_split
3.39% iov_iter_fault_in_readable
2.72% _raw_spin_unlock_irq
2.30% fscrypt_mergeable_bio
2.29% el0_svc_common
2.23% free_unref_page_list
2.02% queue_work_on
1.98% mod_delayed_work_on
1.83% blk_crypto_submit_bio
1.79% clear_page
1.68% _mtk_btag_pidlog_set_pid
1.47% get_page_from_freelist
1.35% f2fs_is_valid_blkaddr
1.18% fscrypt_generate_dun
1.02% __save_stack_trace
0.97% pagecache_get_page
0.95% __handle_speculative_fault
0.82% depot_save_stack
0.80% f2fs_map_blocks
0.73% __rcu_read_unlock
0.67% __pi_memset
0.64% f2fs_wait_on_block_writeback
0.56% __rcu_read_lock
0.54% kmem_cache_alloc
3.查找线程中所用时间的百分比
.so 文件中的执行时间可以跨多个线程分配。您可以运行此命令来查看每个线程所用时间的百分比。
simpleperf report --sort tid,comm
例
Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data
Arch: arm64
Event: cpu-cycles (type 0, config 0)
Samples: 3294
Event count: 1193555038Overhead Tid Command
42.01% 12182 Thread-4
29.48% 11834 RenderThread
16.96% 10167 com.andromeda.androbench2
6.04% 11853 mali-cmar-backe
2.70% 11876 binder:10167_4
1.24% 11854 ged-swd
0.67% 11844 mali-mem-purge
0.62% 12087 binder:10167_6
0.26% 11968 binder:10167_2
0.01% 11820 Jit thread pool
0.00% 11824 FinalizerWatchd
0.00% 11859 GPU completion
4.查找对象模块中所用时间的百分比
在找到占用大部分执行时间的线程之后可以使用此命令来隔离在这些线程上占用最长执行时间的对象模块。
simpleperf report --tids threadID --sort dso
例
Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data
Arch: arm64
Event: cpu-cycles (type 0, config 0)
Samples: 1457
Event count: 501433272Overhead Shared Object
96.72% [kernel.kallsyms]
2.80% /apex/com.android.runtime/lib64/bionic/libc.so
0.33% /apex/com.android.art/lib64/libart.so
0.08% /vendor/lib/modules/memfusion.ko
0.07% /system/lib64/libutils.so
5.了解函数调用的相关性
调用图可直观呈现 Simpleperf 在对会话进行性能剖析期间记录的堆栈轨迹。
您可以使用 report -g 命令打印调用图以查看其他函数调用的函数。这有助于确定是某个函数本身运行缓慢还是因为它调用的一个或多个函数运行较慢。
您还可以使用 Python 脚本 report.py -g 来启动显示函数的交互式工具。您可以点击每个函数查看它的子函数所用的时间。
simpleperf report -g
例
TECNO-KI7:/ # simpleperf report -g
simpleperf E record_file_reader.cpp:83] failed to open record file perf.data: No such file or directory
1|TECNO-KI7:/ # simpleperf report -i /data/perf.data -g
Cmdline: /system/bin/simpleperf record -p 10167 --duration 5 -o /data/perf.data
Arch: arm64
Event: cpu-cycles (type 0, config 0)
Samples: 3294
Event count: 1193555038Children Self Command Pid Tid Shared Object Symbol
3.93% 3.93% Thread-4 10167 12182 [kernel.kallsyms] __blockdev_direct_IO
3.84% 3.84% Thread-4 10167 12182 [kernel.kallsyms] get_user_pages_fast
3.78% 3.78% Thread-4 10167 12182 [kernel.kallsyms] dio_bio_complete
2.55% 2.55% mali-cmar-backe 10167 11853 [kernel.kallsyms] _raw_spin_unlock_irqrestore
2.36% 2.36% Thread-4 10167 12182 [kernel.kallsyms] memblock_start_of_DRAM
2.27% 2.27% Thread-4 10167 12182 [kernel.kallsyms] el0_da
2.12% 2.12% Thread-4 10167 12182 [kernel.kallsyms] blk_queue_split
1.94% 1.94% Thread-4 10167 12182 [kernel.kallsyms] iov_iter_fault_in_readable
1.31% 1.31% Thread-4 10167 12182 [kernel.kallsyms] fscrypt_mergeable_bio
1.27% 1.27% Thread-4 10167 12182 [kernel.kallsyms] free_unref_page_list
1.15% 1.15% RenderThread 10167 11834 [kernel.kallsyms] queue_work_on
1.15% 1.15% Thread-4 10167 12182 /apex/com.android.runtime/lib64/bionic/libc.so memset
1.13% 1.13% Thread-4 10167 12182 [kernel.kallsyms] mod_delayed_work_on
1.05% 1.05% Thread-4 10167 12182 [kernel.kallsyms] blk_crypto_submit_bio
1.02% 1.02% Thread-4 10167 12182 [kernel.kallsyms] clear_page
1.01% 1.01% RenderThread 10167 11834 [kernel.kallsyms] _raw_spin_unlock_irqrestore
0.96% 0.96% Thread-4 10167 12182 [kernel.kallsyms] _mtk_btag_pidlog_set_pid
0.77% 0.77% Thread-4 10167 12182 [kernel.kallsyms] f2fs_is_valid_blkaddr
0.76% 0.76% RenderThread 10167 11834 /apex/com.android.runtime/lib64/bionic/libc.so __vfprintf
0.70% 0.70% RenderThread 10167 11834 [kernel.kallsyms] _raw_spin_unlock_irq
0.68% 0.68% Thread-4 10167 12182 [kernel.kallsyms] fscrypt_generate_dun
0.67% 0.67% Thread-4 10167 12182 [kernel.kallsyms] get_page_from_freelist
0.64% 0.64% RenderThread 10167 11834 [kernel.kallsyms] el0_svc_common
0.62% 0.62% Thread-4 10167 12182 [kernel.kallsyms] _raw_spin_unlock_irqrestore
0.58% 0.58% Thread-4 10167 12182 [kernel.kallsyms] __save_stack_trace
0.55% 0.55% Thread-4 10167 12182 [kernel.kallsyms] pagecache_get_page
0.54% 0.54% com.andromeda.androbench2 10167 10167 /apex/com.android.art/lib64/libart.so ExecuteNterpImpl
0.51% 0.51% Thread-4 10167 12182 [kernel.kallsyms] __handle_speculative_fault
0.46% 0.46% Thread-4 10167 12182 [kernel.kallsyms] f2fs_map_blocks
0.45% 0.45% RenderThread 10167 11834 /apex/com.android.runtime/lib64/bionic/libc.so scudo::Allocatorscudo::AndroidConfig, (scudo_malloc_postinit)
rigin, unsigned long, bool)
0.44% 0.44% RenderThread 10167 11834 /system/lib64/libgui.so plt
0.41% 0.41% Thread-4 10167 12182 [kernel.kallsyms] depot_save_stack
0.36% 0.36% Thread-4 10167 12182 [kernel.kallsyms] f2fs_wait_on_block_writeback
0.36% 0.36% Thread-4 10167 12182 [kernel.kallsyms] _raw_spin_unlock_irq
0.34% 0.34% Thread-4 10167 12182 [kernel.kallsyms] __rcu_read_unlock
0.34% 0.34% com.andromeda.androbench2 10167 10167 [kernel.kallsyms] _raw_spin_unlock_irq
0.32% 0.32% Thread-4 10167 12182 [kernel.kallsyms] __pi_memset
0.31% 0.31% Thread-4 10167 12182 [kernel.kallsyms] kmem_cache_alloc
0.31% 0.31% com.andromeda.androbench2 10167 10167 /apex/com.android.art/lib64/libart.so artAllocStringFromCharsFromCodeRegionTLAB
0.26% 0.26% mali-cmar-backe 10167 11853 [kernel.kallsyms] el0_svc_common
0.26% 0.26% RenderThread 10167 11834 /apex/com.android.runtime/lib64/bionic/libc.so write
0.25% 0.25% Thread-4 10167 12182 [kernel.kallsyms] pte_map_lock
........
6. 获取被剖析程序或系统范围内的原始事件计数器信息
simpleperf stat 被用于获取被剖析程序或系统范围内的原始事件计数器信息。通过传入选项我们可以选择使用哪些事件监视哪个进程/线程监视多长时间以及打印的间隔。
Performance counter statistics:# count event_name # count / runtime17,839,958,825 cpu-cycles # 1.758283 GHz6,411,685,476 stalled-cycles-frontend # 632.274 M/sec5,413,391,502 stalled-cycles-backend # 534.113 M/sec11,755,131,810 instructions # 1.160 G/sec1,409,829,788 branch-instructions # 139.262 M/sec171,458,771 branch-misses # 16.946 M/sec10070.704634(ms) task-clock # 1.006817 cpus used7,210 context-switches # 716.330 /sec94,430 page-faults # 9.387 K/secTotal test time: 10.002513 seconds.
七、参考文档
【Simpleperf】Android的CPU分析性能优化利器_android perf_Yngz_Miao的博客-CSDN博客
Profile 工具系列之四simpleperf_old_man的博客-CSDN博客
使用 Simpleperf 分析本地代码性能 | WolfcsTech
如何读懂火焰图 - 阮一峰的网络日志
Simpleperf介绍 | WolfcsTech
Simpleperf | Android NDK | Android Developers
Simpleperf 命令和选项参考文档 | Android NDK | Android Developers