【用法总结】Systrace使用基础
一、systrace基本介绍
systrace是Android Sdk提供的一个用于分析系统及应用性能的工具。
目前platform-tools最新版本是33.0.3
从33.0.1开始systrace被移除,所以需要下载安装33.0.1的前一个版本33.0.0,下载地址
platform-tools工具路径是在:android_sdk\platform-tools
ps: 需要下载指定版本的platform-tools工具,可通过:https://dl.google.com/android/repository/platform-tools_r${version}-windows.zip的方式拼接,其中的version就是官网发行时的版本号。
被弃用了?
官方最新已经推荐使用perfetto工具了,但是在使用方式上也是基于systrace差不多的模式,并且日常使用还是可以用systrace的,主要看能否满足日常需要,并不是一定要用最新的工具。
二、快捷键用法
二、systrace命令用法
使用下文说明的命令格式,然后在chrome浏览器中,输入:chrome://tracing/,然后点击load选择导出的.html文件即可。
2.1 命令格式:
切换systrce.py文件所在的目录,然后执行如下命格式:
python systrace.py [options] [category1] [category2] ... [categoryN]
2.2 option取值:
option | 说明 |
---|---|
-a | 后跟应用包名,指定抓取的应用报名 |
-o | 后跟文件路径,说明导出到哪个路径,文件名是什么 |
-t N, –time=N | 抓取时长,默认是5s |
-b N, -buf-size=N | buffer的大小(单位:KB),用于限制trace总大小,默认无上限,注意这里限制小了会导致trace抓不全 |
-from-file=<FROM_FILE> | 如果是用atrace直接在shell命令环境中抓取的atrace文件,则需要用这个选项,加上-o <FILE_PATH>来转换成.html后缀的文件,然后用chrome浏览chrome://tracing/去浏览分析trace |
-l, --list-categories | 查看所有可用的category(可抓取的trace维度,比如:am、wm、view、gfx等等) |
2.3 category取值:
category | 说明 |
---|---|
gfx | 图形信息,加上能看到主线程的doFrame和RenderThread的drawFrame过程 |
sched | cpu调度信息 |
view | 视图相关,加上这个就能看到View的测量,布局文件的inflate过程 |
am | Activity Manager服务,加上这个就能看到Application、Activity的启动过过程了 |
wm | 窗口管理服务 |
app | 应用信息,实测好多设备都不支持这个category了 |
webview | WebView相关信息 |
2.4 命令用法举例:
- 查看当前设备支持的category类型:
// 这里要注意和Android系统自带的atrace命令区分开,atrace查看所有的category的命令是:atrace --list_categories
// 前者是横线分隔单词:--list-categories,后者是下划线分隔单词:--list_categories
python systrace.py --list-categories
这里要注意和Android系统自带的atrace命令区分开,atrace查看所有的category的命令是:atrace --list_categories,
前者是横线分隔单词:–list-categories,后者是下划线分隔单词:–list_categories
例如:
admin@adminMacBook-Pro systrace % python systrace.py --list-categories
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
irq - IRQ Events
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
thermal - Thermal event
gfx - Graphics (HAL)
ion - ION allocation (HAL)
NOTE: more categories may be available with adb root
- 抓取com.yyg.anr应用的trace:
python systrace.py -a com.yyg.anr -t 5 -o anr_trace.html sched freq idle am wm gfx view binder_driver hal dalvik camera input res
2.5 快捷键用法:
(1)WASD:W/S:放大/缩小,A/D: 时间轴向左向右移动,同时摁住shift+W/A/S/D时会增加速度
(2)M:聚焦当前选中的区域,并在下方展示具体的耗时
(3)F:放大当前选区
(4)V:高亮Vsync信号
(5)左键/右键:上一个事件,下一个事件
三、systrace报告怎么看?
3.1 CPU调度信息
3.2 线程状态信息
3.2.1 绿色 : 运行中(Running)
3.2.1 蓝色:Runanble状态
3.2.1 白色:Sleeping状态
线程没有工作要做,可能是因为线程在互斥锁上被阻塞。
作用:这里一般是在等事件驱动
3.2.1 橘色:不可中断的睡眠态 (Uninterruptible Sleep - IO Block)
线程在I / O上被阻塞或等待磁盘操作完成,一般底线都会标识出此时的 callsite :wait_on_page_locked_killable
作用:这个一般是标示 io 操作慢,如果有大量的橘色不可中断的睡眠态出现,那么一般是由于进入了低内存状态,申请内存的时候触发 pageFault, linux 系统的 page cache 链表中有时会出现一些还没准备好的 page(即还没把磁盘中的内容完全地读出来) , 而正好此时用户在访问这个 page 时就会出现 wait_on_page_locked_killable 阻塞了. 只有系统当 io 操作很繁忙时, 每笔的 io 操作都需要等待排队时, 极其容易出现且阻塞的时间往往会比较长.
比如com.miui.notification:remote进程有这样的状态:
3.2.1 紫色 : 不可中断的睡眠态(Uninterruptible Sleep)
线程在另一个内核操作(通常是内存管理)上被阻塞。
作用:一般是陷入了内核态,有些情况下是正常的,有些情况下是不正常的,需要按照具体的情况去分析
3.3 线程唤醒信息:
6360线程处于Runanble状态时,蓝色的线程状态区域,是被6456线程唤醒,继续看这个线程是干什么的。
虽然这个线程只能看到tid=6456,但是根据硬件加速打开状态,并且这个线程是紧接着doFrame做drawFrame操作的,可以推断这个是RenderThread线程。
🤨:并不是每个Runnable状态的时间段都能看到唤醒线程,为什么?
推测并不一定是等待同步锁对象导致的Runnable状态,也可能是CPU时间片没分配到。
3.4 帧率信息
帧率信息主要看主线程的doFrame和RenderThread线程drawFrame的trace进行分析。
每一帧就是一个F圆圈,代表调用Choreographer(编舞者)的doFrame()方法耗时
- 圆圈绿色代表Frame渲染流畅
- 黄色和红色代表渲染超过16.6ms,红色的更严重。
- perfetto分析trace上是没有⭕️的,这时候可以选中一段时间,然后看看doFrame+drawFrame执行了多少次,计算出平均帧率分析卡顿程度
3.5 应用启动耗时分析
分析应用启动主要看trace上以下几个阶段:
应用启动几大核心阶段:
四、总结
trace的使用很容易,但在实际分析性能问题又很容易陷入“好像知道该怎么分析,但是实际上又分析不出来个所以然的情况”,其实究其根本还是如下两个关键点:
4.1 trace的每一项信息代表的含义一知半解,不明确
4.2 先熟悉运行逻辑方知如何分析
比如分析卡顿丢帧的trace时,发现主线程的CPU状态有一段时间是Runnable或着sleep状态的,然后根据3.3节介绍的查看唤醒信息时,跟踪到是被RenderThread线程唤醒的,也就是说主线程会因为渲染线程在执行某个任务导致主线程等待。再继续推测很可能是渲染线程上一帧绘制卡了导致没法绘制下一帧,也能看出主线程和渲染线程是有协作关系的,这就需要我们熟悉界面每一帧从测量、布局到绘制,再到传给渲染线程,渲染线程通过c/c++调用到GPU绘制展示到显示器上的过程,否则是很难分析出来根因的,更不知道该怎么修复问题。
再比如说分析应用启动慢问题的trace时,得先知道应用冷启动过程是什么流程,哪些节点是我们能干预的?那么我们就需要先熟悉以下过程:
应用进程不存在的情况下,从点击桌面应用图标,到应用启动,大概会经历以下流程:
- 1、Launcher startActivity
- 2、AMS startActivity
- 3、Zygote fork进程
- 4、ActivityThread main()
- 4.1 ActivityThread attach
- 4.2 handleBindApplication
- 4.3 attachBaseContext
- 4.4 installContentProviders
- 4.5 Application onCreate
- 5、ActivityThread进入loop循环
- 6、Activity生命周期回调,onCreate、onStart、onResume…
整个流程我们能干预的主要是4.3、4.5和6,那么就需要重点关注trace中这几个节点的tag进行分析。
参考文章
[1] Android Systrace 基础知识 – 分析 Systrace 预备知识
[2] Android卡顿掉帧问题分析之工具篇