android studio profiler 性能分析
为什么需要android studio profiler
UE4提供的 UnrealFrontend Profiler 、Unreal Insights等工具也可以支持非shipping版本的移动端性能分析。但是分析工具本身还是或多或少的占用一部分性能。android studio profiler则完全不依赖UE4本身的分析,不影响APP性能,性能分析更为精准。缺点是性能数据的录制时间比较短,太长会卡死。
Profileable
是在 Android Q 中引入的清单配置。它可以指定设备用户能否通过 Android Studio、Simpleperf 和 Perfetto 等工具对此类应用进行性能分析
。
在
profileable
之前,大多数开发者只能对 Android 上的可调试应用进行性能分析,这会导致性能显著下降
。这些性能下降可能会导致分析结果无效,尤其是当它们与时间有关时。
引入了
Profileable
,以便开发者可以选择允许其应用向分析工具公开信息,同时导致的性能下降微乎其微
。可分析 APK 实质上是一个清单文件中添加了一行
<profileable android:shell="true"/>
的发布版 APK。
如需构建可分析应用,您需要先构建发布版应用,然后更新其清单文件,将发布版应用转换为可分析应用。
准备
-
可调试包
目前shipping 中设置了android:debuggable="false" 为可调式包,但缺少调试符号信息展示不全,此处注意。Dev包是可调式的。最好添加Profileable -
Android Studio
版本可以用4.0以上版本,profiler有独立安装包可以直接启动在bin目录下 - AS DebugConfigurations->Debugger->Symbol Directories配置ue4的so目录\arm64\jni\arm64-v8a
- 手机开发者模式
- adb devices 测试手机电脑连接正常
录制
- 手机上打开应用
- 打开android studio profiler 选择手机调试的应用进程
看到如下界面
点击cpu
3. 选择Simpile C/C++ Functions,实时预览性能数据
4. 点击Record录制完成后点击stop
5. 自动生成Trace文件,可导出
数据分析
官网教程:
- as profiler CPU性能录制是按照线程处理的,所以先要选择线程,然后cpu时间线上选择一个时间范围
2. 时间线选择控制,选中一个时段方便观察具体每帧图表或汇总一段时间的图表
可以鼠标左键点击CPU时间线 选择一个时间范围, WSAD按键分别用来:缩小时间范围、放大时间范围、向左移东时间范围、右移动时间范围
3. Call Chart视图:可以看每帧的调用栈的具体耗时,发现具体卡顿点
Call Chart 它基本上就是一个调用栈的重新组织和可视化呈现;横轴就是时间线,用来展示方法开始与结束的确切时间,纵轴则自上而下展示了方法间调用和被调用的关系;
对应用自有函数的调用显示为绿色,对第三方 API(包括 Java 语言 API)的函数调用显示为蓝色。
点击CPU时间线可以看到选中的线程视图会展示出调用堆栈的可视化信息如下图:
鼠标悬浮可以看具体函数的调用时间,通过W可以进一步缩小时间范围观察每帧的调用。
4. Flame Chart火焰图:发现总耗时很长的调用链及其占比
Flame Chart 提供了一个调用栈的聚合信息(合并相同的调用栈)。它的横轴显示的是百分比数值。由于忽略了时间线信息,Flame Chart 可以展示每次调用消耗时间占用整个记录时长的百分比。在顶部展示的是被调用者,底部展示的是调用者。鼠标移动到火焰图上可以看到相关函数的总体调用耗时。
5. Top Down视图: 耗时调用链的排序视图 ,观察其中每一步所消耗的精确时间
以 Flame Chart 为基础,从调用者开始,持续添加被调用者作为子节点,直到整个 Flame Chart 被遍历一遍,然后按照调用链的耗时长短从高到低进排序
6. Bottom Up视图:观察某个方法如何被调用, 找到最耗时的方法调用
从底部开始构建,这样我们就能通过在节点上不断添加调用者来反向构建出树,每个独立节点都可以构建出一棵树。
图表生成原理
图表作用总结
官方教程:
Call Chart
Call Chart 横轴就是时间线,用来展示方法开始与结束的确切时间,纵轴则自上而下展示了方法间调用和被调用的关系。
Flame Chart
根据call char 聚合相同的调用堆栈
Top Down
以 Flame Chart 为基础,您只需要从调用者开始,持续添加被调用者作为子节点,直到整个 Flame Chart 被遍历一遍,您就获得了一个 Top Down Tree
构建步骤:
我们从 A 节点开始:
- A 消耗了 1 秒钟来运行自己的代码,所以 Self Time 是 1;
- 然后它消耗了 9 秒中去调用其他方法,这意味着它的 Children Time 是 9;
- 这样就一共消耗了 10 秒钟,Total Time 是 10;
- B 和 D 以此类推...
- 值得注意的是,D 节点只是调用了 C,自己没做任何事,这种情况在方法封装时很常见。所以 D 的 Children Time 和 Total Time 都是 2。
对于每个节点,我们关注三个时间信息:
- Self Time —— 运行自己的代码所消耗的时间;
- Children Time —— 调用其他方法的时间;
- Total Time —— 前面两者时间之和。
Bottom Up
Bottom Up Tree 从底部开始构建,这样我们就能通过在节点上不断添加调用者来反向构建出树。由于每个独立节点都可以构建出一棵树。
由于我们在构建基于 C 节点的 Bottom Up Tree,所以所有时间信息也都是基于 C 节点的。这时我们在计算 B 的 Self Time 时,应当计算 C 被 B 调用的时间,而不是 B 自身执行的时间,这里是 4 秒;对于 D 来说,则是 2 秒。