这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」
卡顿分析思路
分析问题的整体思路从哲学上来讲基本都差不多:
- 发现问题
- 定位问题
- 量化问题
- 修复问题
卡顿问题也不例外,卡顿问题的最复杂的环节在于定位和修复问题,systrace是一款能够帮助简化定位问题的工具,它将卡顿链路上的事件以时间轴组织并提供可视化的图标显示。
卡顿问题分析过程
- 发现问题 - 视觉卡顿,线上监控,gpu绘制柱状图等都可以帮我们发现页面卡顿情况
- 定位问题 - 全局发现卡顿可以用StrictMode,systrace, BlockCanary等,
- 量化问题 - 局部详细分析可以用TraceView,或者Hugo等打印每个方法耗时,与卡顿标准比较,比如正常人眼在收集到低于20fps的动画时,会认为出现卡顿。
- 修复问题 - 针对具体问题,如Io操作,主线程网络请求,同步等待,频繁gc等,具体问题具体修复。
systrace介绍
- systrace借助ftrace的能力,利用探针在系统关键节点上加入插桩代码,启动线程收集我们需要的信息。
- android的sdk提供了启动systrace的脚本systrace.py,位于Android/sdk/platform-tools/systrace/systrace.py
- 在特定代码中增加Trace.beginSection("TTag")和Trace.endSection,增加自己想收集的TTag,但需要指定收集这些tag.
systrace使用
systrace命令
- systrace.py是android提供的系统工具,位于Android/sdk/platform-tools/systrace/systrace.py
- systrace启动分析命令如下:
python systrace.py [options] [category ...]
python systrace.py -o ~/mytrace.html -a com.hch.ioc gfx view wm am res sync
options说明
option为命令可选项,比较重要的几个参数如下:
- -a <package_name>:这个选项可以开启指定包名App中自定义Trace Label的Trace功能。也就是说,如果你在代码中使用了
Trace.beginSection("tag")
,Trace.endSection
;默认情况下,你的这些代码是不会生效的,指定包名后才会收集。 - -t N:用来指定Trace运行的时间,如果不输入,则需要手动输入enter命令来结束。
- -l:这个用来列出你分析的那个手机系统支持的Trace模块;也就是上面命令中
[category]
的部分;不同版本的系统能支持的模块是不同的, -o FILE:指定trace数据文件的输出路径,如果不指定就是当前目录的trace.html
。
category说明
category指定需要监控的模块,比如am,pm,webview,power等,可以用-l来获得:
systrace.py -l
#在oppo上得到的列表如下
gfx - Graphics
input - Input
view - View System
webview - WebView
wm - Window Manager
am - Activity Manager
sm - Sync Manager
audio - Audio
video - Video
camera - Camera
hal - Hardware Modules
res - Resource Loading
dalvik - Dalvik VM
rs - RenderScript
bionic - Bionic C Library
power - Power Management
pm - Package Manager
ss - System Server
database - Database
network - Network
adb - ADB
vibrator - Vibrator
aidl - AIDL calls
nnapi - NNAPI
rro - Runtime Resource Overlay
pdx - PDX services
sched - CPU Scheduling
freq - CPU Frequency
idle - CPU Idle
disk - Disk I/O
sync - Synchronization
memreclaim - Kernel Memory Reclaim
binder_driver - Binder Kernel driver
binder_lock - Binder global lock trace
gfx - Graphics (HAL)
ion - ION allocation (HAL)
常见的模块说明如下:
sched
: CPU调度的信息,非常重要;你能看到CPU在每个时间段在运行什么线程;线程调度情况,比如锁信息。gfx
:Graphic系统的相关信息,包括SerfaceFlinger,VSYNC消息,Texture,RenderThread等;分析卡顿非常依赖这个。view
: View绘制系统的相关信息,比如onMeasure,onLayout等;对分析卡顿比较有帮助。am
:ActivityManager调用的相关信息;用来分析Activity的启动过程比较有效。dalvik
: 虚拟机相关信息,比如GC停顿等。binder_driver
: Binder驱动的相关信息,如果你怀疑是Binder IPC的问题,不妨打开这个。core_services
: SystemServer中系统核心Service的相关信息,分析特定问题用
常用模块组合说明
- gfx input view hwui 滑动列表测试
- gfx input sched view am wm res 页面秒开测试
- gfx input view dalvik disk GC或者是IO导致的卡顿
- gfx input view res am wm power 电量问题分析
线程状态说明
- 绿色:running正常运行中,点击可以看到运行时长
- 蓝色:Runnable持续时间越长,则表示cpu调度越忙,可能运行的线程太多。
- 白色:sleeping,线程睡眠,需要重点关注UIThread的睡眠情况,选中之后变色了,实际是白色的。
- 橘色:wating阻塞状态,io阻塞,网络阻塞,同步阻塞等。
systrace表操作快捷键
按键操作 作用
w 放大,[+shift]速度更快
s 缩小,[+shift]速度更快
a 左移,[+shift]速度更快
d 右移,[+shift]速度更快
f 放大当前选定区域
m 标记当前选定区域
v 高亮VSync
g 切换是否显示60hz的网格线
0 恢复trace到初始态,这里是数字0而非字母o
h 切换是否显示详情
/ 搜索关键字
enter 显示搜索结果,可通过← →定位搜索结果
` 显示/隐藏脚本控制台
? 显示帮助功能
systrace案例分析
在主Activity的onCreate方法中睡眠500ms
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
启动命令捕获trace文件:
python systrace.py -o ~/mytrace1.html -a com.hch.hive gfx view wm am sched
用chrome打开后如下:
- 1处可以过滤特定的进程,比如我们关注自己的app的进程。
- 2处可以高亮vsync信号
- 3处可以观察整个flow上的每帧的情况,一般橘色或者红色的帧是卡顿帧,需要我们重点分析
- 4处是提示我们出现问题的原因。
- 5处显示线程状态。
实际分析
- 选中特定的进程,一般是自己的app的进程
- 找到左侧frames行,这里会列出每帧耗时,绿色表示帧耗时低于16ms,黄色和红色表示严重卡顿,也就是我们要分析的帧
- 最后发现是线程休眠了500ms