Android性能分析Systrace工具
一、概述
保证系统流畅度,也就是保证系统能连续不间断地提供每秒60帧的运行状态。当出现掉帧时(也可称为Jank),需要知道当前整个系统所处的状态,systrace便是最佳的选择,它能手机检测Android系统各个组件随着时间的运行状态,并能提示该如何有效地修复问题,接下来说说systrace如何使用以及如何解读。
二、Systrace
第1步:如何启动Monitor:
1) 安装完Android SDK并下载platform tools后,在SDK的目录下即可看到Monitor工具:
2) 也可以通过eclipse/Android Studio 启动Monitor:
3) 启动后如下:
说明:如果无法看到设备信息的话,请检查adb连接是否正常。
第2步:如何配置和抓取:
1)点击上图中“用户进程”右上角的systrace按钮会来到如下界面:
说明1:trace输出的文件路径
说明2:配置抓取systrace的时间,通常设置5秒,并在5秒内重现问题,时间太短会导致问题重现时没有被抓到,时间太长会导致JavaHeap不够而无法保存,因此在能抓到问题点的情况下,时间越小越好。
说明3:Buffer Size是存储systrace的size,同样的,太小会导致信息丢失,时间太长会导致JavaHeap不够而无法保存,建议20480。
说明4:如果用户有自己在应用程序中加入自己的systrace log,如下:
Trace.beginSection("newInstance");
Trace.endSection("newInstance");
那么此处必须选择这个应用对应的进程名字,否则新加的systrace log不会被抓到。
说明5:这部分TAG全部使能上。
说明6:针对UI相关的性能问题,以下TAG必须使能:Input/Window Manager/Activity Manager/Bionic C Library/ CPU Freq/CPU Idle/CPU load. 如果设备可以root,root后可以看到更多的TAG,root后请使能:eMMC commands/ Synchonization/Kernel Workqueues.
2) 设置完成后点击“OK"开始抓取systrace,请在此时重现性能问题,设置的时间到后,trace.html文件会被自动保存下来。
第3步:检查systrace是否可用:
使用浏览器打开抓下来的html文件。如果systrace中出现如下很多”Did Not Finish",就是因为BufferSize太小导致信息丢失,此时调整buffer size大小并重新抓取:
出错处理:
1)javaheap space 错误:
这种错误通常是因为内存不足,请按如下步骤检查:
A. BufferSize是不是设置太大了,尽量减少,但是太小会导致信息丢失,以已抓到的systrace不丢失信息为前提,尽量减少bufferSize.
B. 抓的时间太长,在能重现性能问题的范围内,减少时间
C. 手机内存太低?建议用一键清理的软件清理后台任务后再试。
D. 抓取systrace前,点击右下图”垃圾“图标回收部分内存:
2) buffer size 错误:
这种错误是因为buffer size太大,减少buffer size.
如果生成的trace文件无法直接打开,请在chrome中输入:chrome://tracing/,然后选择load按钮,把生成的html load进来
2.2 使用命令行启动Trace(4.3以上系统,api18以上):
命令行
Python systrace.py [options] [category1] [category2] ... [categoryN]
systrace.py在:
android-sdk/platform-tools/systrace
2.2.1 options
其中options可取值:
options | 解释 |
---|---|
-o <FILE> | 输出的目标文件 |
-t N, –time=N | 执行时间,默认5s |
-b N, –buf-size=N | buffer大小(单位kB),用于限制trace总大小,默认无上限 |
-k <KFUNCS>,–ktrace=<KFUNCS> | 追踪kernel函数,用逗号分隔 |
-a <APP_NAME>,–app=<APP_NAME> | 追踪应用包名,用逗号分隔 |
–from-file=<FROM_FILE> | 从文件中创建互动的systrace |
-e <DEVICE_SERIAL>,–serial=<DEVICE_SERIAL> | 指定设备 |
-l, –list-categories | 列举可用的tags |
2.2.2 category
category可取值:
category | 解释 |
---|---|
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 |
app | Application |
res | Resource Loading |
dalvik | Dalvik VM |
rs | RenderScript |
bionic | Bionic C Library |
power | Power Management |
sched | CPU Scheduling |
irq | IRQ Events |
freq | CPU Frequency |
idle | CPU Idle |
disk | Disk I/O |
mmc | eMMC commands |
load | CPU Load |
sync | Synchronization |
workq | Kernel Workqueues |
memreclaim | Kernel Memory Reclaim |
regulators | Voltage and Current Regulators |
2.2.3 示例
例如,在systrace.py所在目录下执行指令:
Python systrace.py -b 32768 -t 5 -o mytrace.html wm gfx input view sched freq
又例如,输出全部的trace信息
Python systrace.py -b 32768 -t 5 -o mytrace.html gfx input view webview wm am sm audio video camera hal app res dalvik rs bionic power sched irq freq idle disk mmc load sync workq memreclaim regulators
注:收集trace,需要提前安装Python,并且一定要注意必须是Python 2.x,而不是能3.x,否则可能会出现问题。另外,buffer大小不可过大,否则会出现oom异常。
2.3 在代码中加入trace (api18以上支持)
你可以自己在一些方法里加入trace 方便自己 跟踪调试 , 如下:
Trace.traceBegin("performTraversals");
try {
} finally {
Trace.traceEnd();
}
你需要保证 traceBegin 与 traceEnd 一定要成对出现。 并且一定要在同一个线程里面。
加入trace的好处在于,生成的trace文件中,会在跟踪的代码段执行对应时间轴区间打上一个tag标记(比如上例中的performTraversals)
如果在代码中加入了trace,在生成trace文件时,必须指定进程为trace所在的进程(前面图中的第四步)
2.4 trace图分析:
纵轴代表着时间线,事件记录按照进程分组,同一个进程内按线程进行纵向拆分,每个线程记录自己的工作,可收缩/展开,如下图:
在本例中,一共有三个组:Kernel, SurfaceFlinger, App,他们分别以包名为标识。每个应用进程都会包含其中所有线程的记录信号,你可以看到从InputEvent到RenderThread都有
除了进程和线程运行信息,还有两个重要信息:
Frame:
在每个app进程,都有一个Frames行,正常情况以绿色的圆点表示。当圆点颜色为黄色或者红色时,意味着这一帧超过16.6ms(即发现丢帧),这时需要通过放大那一帧进一步分析问题。对于Android 5.0(API level 21)或者更高的设备,该问题主要聚焦在UI Thread和Render Thread这两个线程当中。对于更早的版本,则所有工作在UI Thread。
Alerts:
Systrace能自动分析trace中的事件,并能自动高亮性能问题作为一个Alerts,建议调试人员下一步该怎么做。
比如对于丢帧是,点击黄色或红色的Frames圆点便会有相关的提示信息;另外,在systrace的最右侧,有一个Alerts tab可以展开,这里记录着所有的的警告提示信息。
当我们点击了Alerts或者点击右边的Alerts列表中的任何一点我们可以看到在界面的最底部会相对应的优化提示以及可能会出现优化的视频教程链接。
比如上面的提示说你View的draw绘制花的时间太长了,然后我们可以根据Description来很明白的看到提示的内容是什么。
然后我们可以点击一块Frames中的F来查看,同样的它会生成一份跟Alerts类似的报告结果并放在界面的最低端。我们可以通过按下m键查看这一帧到下一帧所花费的时间以及哪个方法被调用的最长。
可以明显看到这时间>16.6ms,系统要求UI的60fps水准所以系统会报出黄色的警告。照样我们从Description中可以读出到底是哪里出了问题
Description
ListView item recycling involved inflating views. Ensure your Adapter#getView() recycles the incoming View, instead of constructing a new one.
- 1
- 2
- 1
- 2
我们可以看出来系统提示你在getView中花费了太多时间没能很有效的复用机制。我们就能顺着这条路去找界面的代码哪里出现了不足从而优化完善。
当然Systrace无法帮你定位到代码里面的具体到某一行代码,但是我们可以通过Alerts和Frames来能基本上优化了不足的地方,然后我们可以根据TraceView来分析具体函数花了多长时间来进一步优化代码提高性能。
上面介绍了Systrace中不同区域的功能。当然最有趣的还是Alerts和Frames两栏,它们展示了通过手机来的数据而生成出来的可视化分析结果。让我们来选择最上方的alerts瞧瞧:
这个警告指出了,有一个View#draw()方法执行了比较长的时间。我们可以在下面看到问题的描述,链接,甚至是相关的视频。下面我们看Frames这一行,可以看到这里展示了被绘制出来的每一帧,并且用绿、黄、红三颜色来区分它们在绘制时的性能。我们选一个红色帧来瞅瞅:
在最下方,我们看到了与这一帧所相关的一些警告。在这三个警告中,有一个是我们上面所提到的(View#draw())。接下来我们在这一帧处放大并在下方展开“Inflation during ListView recycling”这条警告:
我们可以看到警告部分的总耗时,32毫秒,远高于了我们对保障60fps所需的16毫秒绘制时间。同时还有更多的ListView每个条目的绘制时间,大约是6毫秒每个条目,总共五个。而Description描述项中的内容会帮助我们理解问题,甚至提供问题的解决方案。回到我们上一张图片,我们可以在“inflate”这一个块区处放大,并且观察到底是哪些View在被填充过程中耗时比较严重。
下面是另外一个渲染过慢的实例:
在选择了某一帧之后,我们可以按“m”键来高亮这一帧,并且在上方看到了这一部分的耗时,如图,我们看到了这一阵的绘制总共耗时超过19毫秒。而当我们展开这一帧唯一的一个警告时,我们发现了“Scheduling delay”这条错误。
Scheduling delay(调度延迟)的意思就是一个线程在处理一块运算的时候,在很长一段时间都没有被分配到CPU上面做运算,从而导致这个线程在很长一段时间都没有完成工作。我们选择这一帧中最长的一块,从而得到更加详细的信息:
在红框区域内,我们看到了“Wall duration”,他代表着这一区块的开始到结束的耗时。之所以叫作“Wall duration”,是因为他就像是墙上的一个时钟,从线程的一开始就为你计时。
但是,CPU Duration一项中显示了实际CPU在处理这一区块所消耗的时间。
很显然,两个时间的差距还是非常大的。整个区块耗时18毫秒,而在这之中CPU只消耗了4毫秒的时间去运算。这就有点奇怪了,所以我们应该看一下在这整个过程之中,CPU去干吗了。
可以看到,所有四个线程都非常的繁忙。
选择其中的一个线程会告诉我们是哪个程序在占用他,在这里是一个包名为com.udinic.keepbusyapp的程序。在这里,由于另外一个程序占用CPU,导致了我们的程序未能获得足够的CPU资源。
但是这种情况其实是暂时的,因为被其他后台应用占用CPU的情况并不多见(- -),但仍有其他应用的线程或是主线程占用CPU。而Traceview也只能为我们提供一个概览,他的深度是有限的。所以要找到我们app中到底是什么让我们的CPU繁忙,我们还要借助另一个工具——Traceview。
三、 快捷操作
3.1 导航操作
导航操作 | 作用 |
---|---|
w | 放大,[+shift]速度更快 |
s | 缩小,[+shift]速度更快 |
a | 左移,[+shift]速度更快 |
d | 右移,[+shift]速度更快 |
3.2 快捷操作
常用操作 | 作用 |
---|---|
f | 放大当前选定区域 |
m | 标记当前选定区域 |
v | 高亮VSync |
g | 切换是否显示60hz的网格线 |
0 | 恢复trace到初始态,这里是数字0而非字母o |
一般操作 | 作用 |
---|---|
h | 切换是否显示详情 |
/ | 搜索关键字 |
enter | 显示搜索结果,可通过← →定位搜索结果 |
` | 显示/隐藏脚本控制台 |
? | 显示帮助功能 |
四、案例分析
在recyclerview的bindview中使用sleep模拟耗时操作,滚动时会出现明显卡顿
@Override
public void onBindViewHolder(StaggredAdapter.MyHolder holder, int position) {
holder.mivItem.setImageResource(mlstPics.get(position)); Trace.beginSection("aaa");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Trace.endSection();
}
使用systrace跟踪,生成如下分析图
找到分析进程对应的ui线程,线程的纵向信息记录的是调用关系,横向信息记录的是调用顺序,代码中的标记“aaa”标记了sleep的时间段,可以按m键高亮显示这个标记对应的时间段,可以看出以下信息:
1.丢帧,在aaa标记时段的前面,有一帧标红的frame,它跟下一个frame之间间隔事件很长(代码sleep中)
2.调用关系,RV滚动-》bindview-》aaa(sleep)
Android性能分析Systrace工具的更多相关文章
- 正确使用Android性能分析工具——TraceView
http://blog.jobbole.com/78995/ 首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他技术 - 导航条 - 首页 最新文章 IT 职场 前端 - Ja ...
- Android性能分析工具介绍
1. Android系统性能调优工具介绍 http://blog.csdn.net/innost/article/details/9008691 TraceviewSystraceOprofile 2 ...
- [转] Android 性能分析案例
Android 系统的一个工程师(Romain Guy)针对Falcon Pro 应用,撰写了一个Android性能分析的文章.该文章介绍了如何分析一个应用哪里出现了性能瓶颈,导致该应用使用起来不流 ...
- Linux性能分析命令工具汇总
转自:http://rdc.hundsun.com/portal/article/731.html?ref=myread 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章. ...
- Android 性能分析工具 TraceView
官方地址 http://developer.android.com/tools/debugging/debugging-tracing.html 推荐:http://blog.csdn.net/inn ...
- [Android Pro] Android 性能分析工具dumpsys的使用
reference to : http://www.open-open.com/lib/view/open1405061994872.html Android提供的dumpsys工具可以用于查看感兴趣 ...
- Android 性能分析工具dumpsys的使用(自己增加一部分在后面)
Android提供的dumpsys工具可以用于查看感兴趣的系统服务信息与状态,手机连接电脑后可以直接命令行执行adb shell dumpsys 查看所有支持的Service但是这样输出的太多,可以通 ...
- android 性能分析、优化
.主要介绍了一些分析工具,比如GT.ITest等http://www.jianshu.com/p/8b77d394b2a6 .详细介绍啦android平台常见性能优化工具http://blog.csd ...
- 【Java/Android性能优3】Android性能调优工具TraceView使用介绍
本文转自:http://blog.csdn.net/innost/article/details/9008691 在软件开发过程中,想必很多读者都遇到过系统性能问题.而解决系统性能问题的几个主要步骤是 ...
随机推荐
- Linux的bond模式绑定及模式区别
[Linux的bond模式配置] 原理: 多块网卡虚拟成一张,实现冗余:多张网卡对外显示一张,具有同一个IP: 工作在网卡是混杂模式的情况下: 对于多物理网卡的 Bond 网卡而言,其中一块物理网卡会 ...
- makefile .phony targets
Phony Targets PHONY 目标并非实际的文件名:只是在显式请求时执行命令的名字.有两种理由需要使用PHONY 目标:避免和同名文件冲突,改善性能. 如果编写一个规则,并不产生目标文件,则 ...
- Swift 动画片段
UIView.transitionWithView( self.WeatherDetailsView, duration: 0.7, options: .TransitionCrossDissolve ...
- 4、数据类型二:Lists
1.关于list的组织形式 列表数据类型(Lists)可以存储一个有序的字符串列表,常用的操作时向列表两段添加元素,或者获取列表的某一个片段.列表类型的底层实现是一个双向链表(double linke ...
- python学习——练习题(10)
""" 题目:暂停一秒输出,并格式化当前时间. """ import sys import time def answer1(): &quo ...
- error C2039: 'SetDefaultDllDirectories'错误解决办法<转>
使用VS2013+WDK8.1+Win7开发UMDF驱动,当使用了CComPtr类,包含了atlcomcli.h头文件却报错,错误如下: Error 3 error C2039: 'SetDefaul ...
- ffmpeg强制使用TCP方式读取rtsp流
ffmpeg强制使用TCP方式处理rtsp流,参考网上资料,得知可以使用如下命令: “ffmpeg -rtsp_transport tcp -i rtsp://admin.......” 可以是使用抓 ...
- SignalR web实时同步 消息推送 广播
源码:https://github.com/SignalR/SignalR demo:http://download.csdn.net/download/qq_21533697/9702791#com ...
- 手游为什么要热更新,C#为什么不能热更新,LUA为什么可以
热更新是什么?简单的说就是打补丁,只补需要部分,不用重个游戏包重打上传 热更新问题的本质是代码更新而不是资源更新,为什么呢? 大型手游都是将补丁资源放在专门的WEB服务器上,游戏启动时动态下载并放入到 ...
- overflow与underflow
是新近的firefox浏览器中支持overflow, underflow这两个事件,当某一元素的大小超出父元素的显示范围就会触发overflow事件,如果从超出显示再变回不超出的状态则触发underf ...