systrace卡顿分析神器

3,108 阅读5分钟

这是我参与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阻塞,网络阻塞,同步阻塞等。 image.png

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打开后如下: image.png

  • 1处可以过滤特定的进程,比如我们关注自己的app的进程。
  • 2处可以高亮vsync信号
  • 3处可以观察整个flow上的每帧的情况,一般橘色或者红色的帧是卡顿帧,需要我们重点分析
  • 4处是提示我们出现问题的原因。
  • 5处显示线程状态。

实际分析

  • 选中特定的进程,一般是自己的app的进程 image.png
  • 找到左侧frames行,这里会列出每帧耗时,绿色表示帧耗时低于16ms,黄色和红色表示严重卡顿,也就是我们要分析的帧 image.png
  • 最后发现是线程休眠了500ms image.png