性能优化——卡顿检测之TraceView、Systrace

1,卡顿的原因

界面绘制:主要原因是绘制的层级深、页面复杂、刷新不合理,由于这些原因导致卡顿的场景更多出现在UI和启动后的初始界面以及跳转到页面的绘制上。
数据处理:导致这种卡顿场景的原因是数据处理量太大,一般分为三种情况,一是数据处理在UI线程(这种应该避免),二是数据处理占用CPU高,导致主线程拿不到时间片,三是内存增加导致GC频繁,从而引起卡顿。
先行了解下Android的UI刷新机制:Android Project Butter分析

2,Profile GPU Rendering

从应用层绘制一个页面(View),主要有三个过程:CPU准备数据→GPU从数据缓存列表获取数据→Display设备绘制,这三个过程的耗时可以通过一个手机开发辅助工具查看:Profile GPU Rendering。Profile GPU Rendering是系统提供的UI绘制检测工具,在设置开发者选项中可以打开,打开后显示如下:

图1、Profile GPU Rendering

它是一个图形监测工具,能实时反应当前绘制的耗时。横轴表示时间,纵轴表示每一帧的耗时(单位为ms)。随着时间推移,从左到右的刷新呈现。提供了一个标准的耗时,如果高于标准耗时,表示当前这一帧丢失。
每一条柱状图都由4种颜色组成:红、黄、蓝、紫,这些线对应每一帧在不同阶段的实际耗时。

蓝色:代表测量绘制的时间,就是记录了在屏幕上更新视图需要花费的时间,也可以理解为执行每一个View的onDraw方法,创建或者更新每一个View的Display List对象。在蓝色的线很高时,有可能是因为需要重新绘制,或者自定义视图的onDraw函数处理事情太多。
红色:代表执行的时间,这部分是Android进行2D渲染通过API将数据发送到GPU,最终在屏幕上显示出来。当红色的线非常高时,可能是由重新提交了视图而导致的。
橙色:表示处理时间,或者是CPU告诉GPU渲染一帧的地方,这是一个阻塞调用,因为CPU会一直等待GPU发出接到命令的回复,如果柱状图很高,就意味着GPU太繁忙了。
·绿色(紫色):表示将资源转移到渲染线程的时间,只有Android 4.0及以上版本才会提供。

任何时候超过绿线(警戒线,对应时长16ms),就有可能丢失一帧的内容,虽然对于大部分应用来说,丢失几帧确实感觉不出卡顿,但保持UI流畅的关键就在于让这些垂直的柱状条尽可能地保持在绿线下面。但是这个Profile GPU Rendering工具是提供我们肉眼看一个页面的绘制情况的直观表现,一般并不会帮我们找到代码中哪些不合理的地方,需要其它工具才可以。

3,TraceView

TraceView是Android SDK提供的性能检测工具,它是一个图形工具,可以检测Android应用层和Framework层的代码执行情况,形成一个图表,从中可以分析出每个方法的执行时间。

1,TraceView的GUI使用方式:

(1)使用方式:AndroidStudio——Tools——Android——Android Device Monitor
(2)单击Strart Method Profiling按钮,如下图:

图2、单击Strart Method Profiling按钮
图3、单击Stop Method Profiling按钮

(3)开启后,在需要检测的路径上做一些操作,例如滑动列表,跳转Activity等等,然后点击Stop Metod Profiling,结果出生成如下图所示的结果图表:

图4、TraceView图表界面
2,TraceView的代码使用方式:

上面的GUI使用方式不太明确,也不精确,很难控制操作的路径,有个更好的方式就是在代码中控制执行的流程,在android.os.Debug类中提供了startMethodTracing和stopMethodTracing方法,前面用来设置开始检测的位置,后面设置结束检测的位置,例如:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(layoutManager);
        mDataSource = new ArrayList<>();
        myAdapter = new MyAdapter(mDataSource);
        mRecyclerView.setAdapter(myAdapter);

        Debug.startMethodTracing("ui_trace");
        addDataSource();
        Debug.stopMethodTracing();
        myAdapter.refreshData(mDataSource);
    }

    private void addDataSource() {
        for (int i = 0; i < 100; i++) {
            mDataSource.add(new ItemBean(R.mipmap.ic_launcher, "This is Data No." + i));
        }
    }

注意:在startMethodTracing方法中需要传入一个文件名,那么系统执行到这段代码时,会自动在指定的目录下创建一个.trace的文件。因为涉及了IO操作,还需要WRITE_EXTERNAL_STORAGE权限。

3,TraceView的面板

Traceview视图分两部分,上半部分为时间片面板(Timeline Panel),下半部分为分析面板(Profile Panel)。

图5、时间片面板

X轴表示时间消耗,单位为毫秒(ms),Y轴表示各个线程,每个线程中的不同方法使用了不同的颜色来表示,颜色占用面积越宽,表示该方法占用CPU时间越长。
时间片面板可以放大/缩小,也可以指定区域放到最大,方便查看具体的过程,一般优先选择放大耗时严重的区域。

图6、分析面板
图7、分析片面板的各列的含义

使用TraceView查看耗时,主要关注Calls+Recur Calls/Total和Cpu Time/Call这两个值,也就是关注调用次数多和耗时久的方法,然后优化这些方法的逻辑和调用次数,减少耗时。
注意:RealTime与cputime区别为:因为RealTime包括了CPU的上下文切换、阻塞、GC等,所以RealTime方法的实际执行时间要比CPU Time稍微长一点。

4,Systrace

Systrace是Android 4.1及以上版本提供的性能数据采样和分析工具。它可以帮助开发者收集Android关键子系统(如surfaceflinger、WindowManagerService等Framework部分关键模块、服务,View系统等)的运行信息,从而帮助开发者更直观地分析系统瓶颈,改进性能。Systrace的功能包括跟踪系统的I/O操作、内核工作队列、CPU负载等,在UI显示性能分析上提供很好的数据,特别是在动画播放不流畅、渲染卡等问题上。Systrace工具可以跟踪、收集、检查定时信息,可以很直观地查看CPU周期消耗的具体时间,显示每个线程和进程的跟踪信息,使用不同颜色来突出问题的严重性,并提供如何解决这些问题的建议。
注意:由于Systrace是以系统的角度返回一些信息,并不能定位到具体耗时的方法,要进一步获取CPU满负荷运行的原因,就需要使用前面介绍过的工具Traceview。

1,Systrace的GUI使用方式

(1)使用方式:AndroidStudio——Tools——Android——Android Device Monitor
(2)点击Systrace,设置好trace文件保存的路径和检测的时间,默认是5s

图8、开启Systrace

(3)然后在应用中进行一些操作
(4)在设置的时间结束后,会在指定的目录下生成一个trace.html的文件,这个文件需要使用Google Chrome浏览器打开查看。

2,Systrace的代码使用方式

Systrace不会追踪应用的所有工作,所以在有需求的情况下,需要添加要追踪的代码部分。可以通过Trace类来实现这个功能,即Trace.beginSection()与Trace.endSection()之间的代码工作会一直被追踪。
注意:
在Trace被嵌套在另一个Trace中时,endSection()方法只会结束离它最近的一个beginSection(String),即在一个Trace的过程中是无法中断其他Trace的。所以要保证endSection()与beginSection(String)调用次数匹配。
Trace的begin与end必须在同一线程中执行。

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private MyAdapter myAdapter;
    private List<ItemBean> mDataSource;

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(layoutManager);
        mDataSource = new ArrayList<>();
        myAdapter = new MyAdapter(mDataSource);
        mRecyclerView.setAdapter(myAdapter);

        
        Trace.beginSection("systrace");
        SystemClock.sleep(2000);
        addDataSource();
        Trace.endSection();
        myAdapter.refreshData(mDataSource);
    }

    private void addDataSource() {
        for (int i = 0; i < 100; i++) {
            mDataSource.add(new ItemBean(R.mipmap.ic_launcher, "This is Data No." + i));
        }
    }
}
图9,Systrace生成的文件打开后

上面就是Systrace生成的.html的文件在chrome中打开后的样子,比较长,但是我们可以通过键盘上的awsd四个键移动和缩放视图,其中我们比较关注的是Alerts和Frame两个数据。
(1)Alerts


图10、Alerts视图

图中发现Alerts上有些数据,单击每个数据都可以在下面看到每个数据代表的含义和描述。
(2)Frame

图11、Frame视图

每个应用都有一行专门显示frame,每一帧就显示为一个灰色的圆圈。当显示为黄色或者红色时,它的渲染时间超过了16.6ms(即达不到60fps的水准)。使用W键放大,看看这一帧的渲染过程中系统到底做了什么,同时它会将任何它认为性能有问题的东西都高亮警告,并提示要怎么优化。
但是,如果想知道UI线程怎么会花费这么多时间的话,就需要使用TraceView,来分析具体是哪些函数在消耗时间。


参考资料:
Android Project Butter分析
Android 编程下的 TraceView 简介及其案例实战
Android 性能优化 二 TraceView工具的使用
Android系统性能调优工具介绍
使用Systrace分析UI性能

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容