Android CPU Profiler性能分析器
CPU性能分析器主要用于捕获、分析CPU使用的情况,通过捕获的信息可以分析应用的CPU使用率、线程活动、函数调用及其开销时间、与系统交互的流程等。通过分析CPU的使用可以优化应用的CPU的使用率,有效提升应用的流畅性、提升用户使用体验、较少电量消耗提升使用时间等
CPU 性能分析器概览
按以下步骤打开CPU性能分析器:
- 依次选择View——》Tool windows——》Profiler或者点击工具栏中的Profiler图标
- 点击CPU时间抽上的任意位置打开CPU性能分析器
当打开CPU性能分析时,它会立即显示应用的CPU使用率和线程活动情况,如下图所示:
CPU性能分析1.png
1、事件时间轴:显示应用中的activity在其生命周期内不断转换经历的各种不同状态过程,如touch(down、press等)事件、屏幕选中等。
2、CPU时间轴:显示应用的实时CPU使用率(以占总可以CPU的百分比表示)、其他应用的实时CPU使用率、应用当前使用的线程总数。
3、线程活动时间轴:这里会列出应用的每个线程,使用一下不同颜色表示它们的活动情况:
- 绿色:表示线程处于活动状态或者准备使用CPU。代表线程正在运行或者可运行状态
- 黄色:表示线程处于活动状态,但它正在等待一个项IO操作(如磁盘读写、请求网络等),然后才能完成它的工作。
- 灰色:表示线程正在休眠且没有消耗任何CPU时间。当线程需要访问尚不可用的资源时,就会出现这种情况,在这种情况下,要么线程进入休眠状态,要么内核将线程置于休眠状态,知道所有资源可用。
捕获CPU使用信息
在CPU性能分析器中,可以根据需要捕获不同的数据:
- Java Method Sample Recording(Java 方法采样):对Java方法的CPU使用信息进行采用、捕获记录,它是在应用的Java执行期间,频繁捕获应用的调用堆栈,分析器依据捕获的堆栈信息推倒出于应用的Java代码执行有关的时间和资源使用情况。重点:通过捕获堆栈分析Java方法代码执行的时间及资源使用情况(不是java方法调用的所有细节都会捕获到)。
- Java Method Trace Recording(跟踪java方法):追踪java方法会记录每个java方法开始调用和结束调用的时间戳,系统会收集比较这些时间戳,用于生成方法追踪数据,包括方法调用花费时间和CPU使用率。这种捕获方式会影响APP的运行效率。
- C/C++ Function Reacording(对C/C++函数采样):与Java 方法采样类似,不过这里是对原生C/C++方法的采样,通过捕获原生C/C++的堆栈来追踪原生方法的CPU使用情况,包括时间开销、CPU使用率等。这种捕获方式只支持Android8.0+的设备。
- System Tracing Recording(追踪系统调用):会捕获应用与系统资源交互的细节,如:线程当前状态的确切时间和持续时间及与系统交互的情况、渲染情况、CPU调度情况等。注重点在于系统调用的细节,一般用于性能瓶颈分析
可以在代码中调用系统提供的API,捕获追踪对应的CPU使用信息,如:
- Debug.startMethodTracingSampling和Debug.stopMethodTracing对应的是捕获java方法采样
- Debug.startMethodTracing和Debug.stopMethodTracing对应的是跟踪java方法
- Trace.beginSection和Trace.endSection对应的是追踪系统调用
也可以在CPU分析器中勾选要捕获记录CPU的配置信息,点击开始即可可是捕获,点击停止捕获后CPU性能分析器会自动打开捕获到的记录CPU活动的信息。
也可以在命令行使用systrace和traceview的命令捕获systrace和traceview的追踪数据进行分析。
要使用Android Studio捕获应用启动时自动开始记录CPU使用信息,可以执行以下操作:
- 依次选择Run——》Edit Configurations
- 在Profiler标签中,勾选Start recording a method trace on startup复选框
- 从菜单中选择CPU记录配置
- 点击apply
- 依次选择Run——》Profile,将应用部署到Android8.0+的设备上
分析
捕获到记录CPU活动的信息之后,CPU性能分析器会自动打开追踪的日志文件,如下图:
[图片上传失败...(image-60165a-1649840871050)]
1、Display显示图形流水线信息:
- Frames: 显示应用中UI线程和渲染线程的轨迹,可以理解为显示每帧的开销情况,标红表示此帧绘制时间超过16ms,存在性能问题,我们主要关注的也是标红的部分
- SurfaceFlinger: 此部分显示SurfaceFlinger处理帧缓存区的时间。SurfaceFlinger是负责将缓存区内容发送到显示屏的系统进程。
- VSYNC: 此部分显示VSYNC,是一个表示与显示流水线保持同步的信号。如果轨迹上出现VSYNC-app信号,这个信号会在应用启动时间过晚时显示,发生这种情况一般是UI线程处于过于忙碌状态。在动画播放期间,它会导致屏幕上出现可见的闪烁,且在动画或者滚动完成之前,会持续带来额外的输入延迟。
- BufferQueue: 此部分显示有多少帧缓冲区在排队等待SurfaceFlinger使用。
2、活动线程状态信息:记录的是线程与界面界面程序相关信息,如:inflate、layout、draw等方法的调用及开销情况
3、Top Down:所有线程中函数调用情况,Top Down中显示每个方法调用所花的CPU时间:
- self:方法内部调用自己的代码所花的时间(不含执行其他方法的时间)
- children: 方法内部执行其他方法所花的时间
-
total: self和children的总和。表示应用在调用执行方法的总时间
4、Flame chart: 以倒置图表的方式显示方法调用情况,如下图所示:
flameChart.png
上图中是Top Down函数调用按逆序用图表的方式进行展示,如:依次调用了:
main——》xxx.initFnSDK——》xxx.loader......
tt_pangle_thread_pll_report1——》xxxThread.run.....
......
鼠标移到每个条目上都会响应的显示在相对时间段内执行该方法所花费的时间(包括self和childred)
5、Bottom Up: 函数被调用情况,方法默认按占用CPU时间由多到少的顺序对排序显示,展开是调用此方法的方法列表。
我们可以:
- 通过在Top Down和Bottom Up中查看方法调用和被调用的情况及其开销时间,排查java方法层面性能问题。
-
通过排查Display中Frames被标红的部分,ctrl + 滑动鼠标滚轮放大(或者按w键减小放大,s键缩小,a键左移,d键右移),查看各个线程的调用情况,特别是UI线程、renderThread,如下图所示:
frames.png
放大之后,我们通过分析ui线程中各ui相关方法的开销,如traversal方法,点击它可以在后侧展示此方法的Top Down、Flame Chart、Bottom Up等情况