2015年伊始,Google发布了关于Android性能优化典范的专题, 一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App。课程专题不仅仅介绍了Android系统中有关性能问题的底层工作原理,同时也介绍了如何通过工具来找出性能问题以及提升性能的建议。主要从三个 方面展开,Android的渲染机制,内存与GC,电量优化。下面是对这些问题和建议的总结梳理
Render Performance
Android 系统带给用户最最广大的感知就是:卡顿。而这背后所隐藏的根本的技术问题就是:渲染性能。其实这是一个矛盾体,它基本是基于这样一个事实:
1、设计师从用户的视觉出发,常常会为APP设计一套基于绚丽的动画、图片等时尚元素来实现流畅的用户体验。
2、Android系统很有可能无法及时完成那些复杂的界面渲染操作。
于是这就造成了这个现象:卡顿。
现在我们来看看Android是怎样处理这个过程的。
Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染, 如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。
当然这是理想的情况。现在我们还看另一种情况:
如果你的某个操作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。
下面我们还说说一种常见的情形。我们经常会给listView滚动时添加些动画效果,这样在用户使用起来会一种炫酷的体验,当然理想情况下应该是这样的。但我们在实际的操作过程发现,这样做会在用户滚动listView是带来卡顿。有很多原因可以导致丢帧,也许是:
- 因为你的layout太过复杂,无法在16ms内完成渲染,
- 有可能是因为你的UI上有层叠太多的绘制单元,
- 还有可能是因为动画执行的次数过多。
这些都会导致CPU或者GPU负载过重。
出了问题,那我们就要想办法定位并企图解决这些个问题。幸运的是我们有一些很有用的工具还帮助我们定位问题。比如
1. 可以使用HierarchyViewer来查找Activity中的布局是否过于复杂,
2. 也可以使用手机设置里面的开发者选项,打开Show GPU Overdraw等选项进行观察。
3. 还可以使用TraceView来观察CPU的执行情况,更加快捷的找到性能瓶颈。
Understanding Overdraw
Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次的UI结构里面,如果不可见的UI也在做绘制的操作,这就会导致某些像素区域被绘制了多次。这就浪费大量的CPU以及GPU资源。
当我们的设计师在设计上追求更华丽的视觉效果的时,我们的程序员就越容易陷入采用越来越多的层叠组件来实现这种视觉效果的怪圈。这很容易导致大量的性能问题,我们必须尽量减少Overdraw的情况发生,来满足APP获得最佳的性能。
幸运的是,我们可以通过手机设置里面的开发者选项,打开Show GPU Overdraw的选项,可以观察UI上的Overdraw情况。
上面的图示就给出了一些例子。蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。
我们可以举例说说可能的原因:
1. 有时候是因为你的UI布局存在大量重叠的部分,
2. 还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景,然后里面的Layout又有自己的背景,同时子View又分别有自己的背景。仅仅是通过移除非必须的背景图片,这就能够减少大量的红色Overdraw区域,增加蓝色区域的占比。这一措施能够显著提升程序性能。
Understanding VSYNC
为了理解App是如何进行渲染的,我们必须了解手机硬件是如何工作,那么就必须理解什么是VSYNC。
在讲解VSYNC之前,我们需要了解两个相关的概念:
- Refresh Rate:代表了屏幕在一秒内刷新屏幕的次数,这取决于硬件的固定参数,例如60Hz。
- Frame Rate:代表了GPU在一秒内绘制操作的帧数,例如30fps,60fps。
GPU会获取图形数据进行渲染,然后硬件负责把渲染后的内容呈现到屏幕上,他们两者不停的进行协作。
理解图像渲染里面的双重与三重缓存机制,这个概念比较复杂,请移步查看Graphics以及《了解Android 4.1之三:黄油项目 —— 运作机理及新鲜玩意》。
理想的状况是:帧率超过刷新频率。在超过60fps的情况下,GPU所产生的帧数据会因为等待VSYNC的刷新信息而被Hold住,这样能够保持每次刷新都有实际的新的数据可以显示。但是我们遇到更多的情况是帧率小于刷新频率。
在这种情况下,某些帧显示的画面内容就会与上一帧的画面相同。更糟糕的事情是,帧率从超过60fps突然掉到60fps以下,这样就会发生LAG,JANK,HITCHING等卡顿掉帧的不顺滑的情况。这也是用户感受不好的原因所在。
Tool:Profile GPU Rendering
性能问题如此的麻烦,幸好我们可以有工具来进行调试。打开手机里面的开发者选项,选择Profile GPU Rendering,选中On screen as bars的选项。
选择了这样以后,我们可以在手机画面上看到丰富的GPU绘制图形信息,分别关于StatusBar,NavBar,激活的程序Activity区域的GPU Rending信息。
随着界面的刷新,界面上会滚动显示垂直的柱状图来表示每帧画面所需要渲染的时间,柱状图越高表示花费的渲染时间越长。
中间有一根绿色的横线,代表16ms,我们需要确保每一帧花费的总时间都低于这条横线,这样才能够避免出现卡顿的问题。
每一条柱状线都包含三部分,蓝色代表测量绘制Display List的时间,红色代表OpenGL渲染Display List所需要的时间,黄色代表CPU等待GPU处理的时间。