应用卡顿优化

概要

应用运行时的卡顿问题非常影响用户体验,严重降低产品表现力,本文将介绍应用卡顿原因以及分析方法等等。

卡顿问题可分为两类,应用卡顿和系统卡顿,本文针对系统正常时应用卡顿场景。

黄油工程

Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。

如上图,第1帧在显示时,GPU并没有准备好第2帧数据,导致第1帧数据连续显示两次,导致不流畅、卡顿。应用需要减轻UI线程负担,将耗时工作放入工作线程中,同时精简绘制工作,保证16ms内可以完成一帧绘制。

图层叠加

Android通过图层叠加完成绘制。

左侧的对象是生成图形缓冲区的渲染器,如主屏幕、状态栏和系统界面。SurfaceFlinger 是合成器,屏幕负责显示合成界面。

应用界面层级应该尽量精简,同时减少过度绘制问题,减轻系统压力。

卡顿原因

应用卡顿常见的原因,UI线程负荷过重,绘制代码不当等。系统卡顿或资源紧张也有可能导致应用卡顿,gc过多也能导致卡顿。此外,过度绘制,界面层级过多也会导致绘制效率下降。

在某些GPU性能较差的机器上,alpha动画效率低下,也会导致卡顿。

分析方法

遇到卡顿问题,从现象入手,排除系统卡顿原因,接下来可通过log分析、工具定位解决卡顿问题。常用工具为traceview,systrace等。

Traceview,针对单一应用,统计具体一段时间内方法执行时间、次数等信息。

Systrace,记录整机运行情况,包括cpu使用情况,vsync信号,gc信息等等,它也能记录部分方法的执行情况,时间等。

Log分析,重点跟踪gc情况,具体业务逻辑流程等。

Traceview

Traceview有两种使用方式,既可使用DDMS采集数据,也可使用Debug类采集数据。使用DDMS采集数据的步骤如下:

  • 在应用的AndroidManifest.xml添加 android:debuggable="true",打开debug属性
  • 打开DDMS面板,选中调试的应用
  • 点击 Start Method Profiling 按钮
  • 操作机器,执行对应需要性能分析的过程
  • 点击 Stop Method Profiling 按钮

抓取数据完成后会自动跳转到traceview界面。

除了使用DDMS采集数据,也可以使用Debug类采集数据,使用Debug类采集数据步骤如下:

  • 在AndroidManifest.xml中添加写sd卡权限
  • 在问题怀疑点处调用Debug.startMethodTracing("demo");
  • 在问题结束点处调用Debug.stopMethodTracing();,例如,可以在Activity的onCreate和onPause处分别调用上述方法。
  • 从sd卡中导致trace文件到pc端,利用ddms打开trace文件。

DDMS方式简单,但很粗略。而使用Debug类采集数据,相对复杂,但更精确。

Traceview分析面板上,有很多的维度,一般来说,我们需要分析出那些耗时或者调用次数过多的函数,耗时的函数可通过维度Incl CPU Time分析。调用次数过多的函数可通过Cpu Time/Call维度分析。耗时的函数需要分析,很容易理解,但调用次数过多的函数很容易被忽略,如果view的onMeasure函数在不需要刷新时被调用多次,这也是值得关注的问题,所以需要分析函数的调用次数。

Traceview应用

模拟如下场景,ListView滑动卡顿,在getView方法中sleep一段时间,导致一帧数据无法在16ms内准备完成,因此滑动卡顿。

  public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        。。。。。。
        try {
            Thread.sleep(50);
        } catch (Exception e) {
        }
        return convertView;
    }

使用DDMS采集数据分析,按Incl CPU Time降序排列,traceview面板如下:

因为Incl CPU Time是包含内部调用的其它函数时间的,所以从上到下,花时间最多的就是虚拟机相关方法以及ActivityThread的main方法(应用线程启动的入口方法)等。点击每一个方法,均可以看到此方法自身花费时间、调用其它方法花费时间以及它的前一调用方法。一般来说通过跟踪调用链,可找到对应问题所在。

从ActivityThread的main方法入手,parents属性不用管,查看children属性,self即是自身花费时间,此时为0,可见耗时是花在loop方法,一跟跟踪调用链最终发现如下:

Adapter类的getView方法中调用了sleep方法以及setImageResource方法,而sleep方法耗时占用整体耗时的97%,如此,问题原凶已找到。

有一个小窍门,在分析某个方法的耗时构成时,如果此方法显示有多个子方法耗时时,则选取耗时比较最大的子方法继续分析,如下下面的情况:

我们预先已知listview滑动卡顿,那么耗时最多的应该是与listview相关的函数,而事实也是如此,继续跟踪线框内容,即可找到最终问题。

Systrace

Systrace与Traceview所不同的是,Systrace它能提供丰富得多的信息,它是对整机这段时间内的全面信息反馈,可以查看cpu分配情况,查看vsync信号,查看应用具体一帧图像各阶段耗时情况,甚至还可以查看gc情况,所以Systrace可以从系统高度,整体高度来查看卡顿问题。如果是分析单一应用卡顿问题,一定要通过Systrace来排除系统问题,确认这段时间内cpu资源足够,也要查看gc情况。如果某段时间内,应用一帧卡顿,而cpu资源不够或此时正在gc,则并不能说明是应用的问题。

由于google对android studio的大力推荐,现在使用eclipse抓取的Systrace,已经无法被chrome识别了,所以需要as抓取Systrace,抓取并打开Systrace的步骤如下:

  • 打开as,打开tools菜单,打开android device monitor
  • 点击抓取systrace按钮,勾选所需的信息,再确定
  • 在机器上进行相应操作,生成对应trace文件
  • 打开chrome浏览器,在地址栏上输入chrome://tracing/,再使用chrome打开之前保存的trace文件

Systrace使用W放大,S缩小,A左移,D右移,右侧有选择条,可选择鼠标点击,也可选择时间段标记。操作较为简单,不再详述。

Systrace有几个需要注意的点,首先就是cpu的状态问题。例如上图红框所示,obtainView方法上是无色的,而右边小部分确是蓝色或绿色,无色则代表cpu此时在睡眠状态,蓝色或绿色表示cpu处于运行状态。如上图所示,则可知此时cpu状态异常,是否是调用了sleep方法导致这一帧卡顿了?可使用左键滑动选中一段距离,查看这段距离的cpu情况:

Systrace也是可以直接点击红色帧(红色帧即是卡顿帧),查看红色帧的一些基本情况,也能看到对于红色帧的处理意见。

Systrace还能够显示当前的gc情况,例如:

Systrace还有一个强大的功能,选中查看某段时间内cpu的情况,如下图所示,cpu这段时间内有gc操作,binder调用,还有打印log,如果gc操作过于频繁,binder调用都是会影响系统性能的,另外log过多也是会影响系统性能的。

章节中的示例,抓取Systrace,分析,案例简单,在Systrace上也一目了解,obtainView时间太长了,原因是cpu那段时间都处于sleep状态。

性能优化的其它方法

前文介绍的是解决卡顿问题的重型武器,也有一些方法可以缓解卡顿或者让性能更好。通过绘制原理的介绍,可以清楚地知道,如果UI的层级越少越好。怎么查看UI的层级呢?可以通过hierarchyviewer工具。可以通过自定义view形式实现UI层级的减少。UI层级减少,也会缓解过度绘制问题。

另外,减少界面刷新的次数也很重要,避免不必要的UI界面刷新。降低UI层级以及减少不必要刷新次数较为简单,不再详述。

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

推荐阅读更多精彩内容