一个 Android 应用是否流畅,或者说是否存在卡顿、丢帧现象,都与 60fps 和 16ms 有关 。那么这两个值是怎么来的呢?为什么以这两个值为衡量标准呢?本文主要讨论下渲染性能方面决定 Android 应用流畅性的因素 。
- 12fps(帧/秒)
- 24fps
- 30fps
- 60fps
- 85fps
所以,总体而言,帧率越高体验越好 。一般的电影拍摄及播放帧率均为每秒 24 帧,但是据称《霍比特人:意外旅程》是第一部以每秒 48 帧拍摄及播放的电影,观众认为其逼真度得到了显著的提示 。
目前,大多数显示器根据其设定按 30Hz、 60Hz、 120Hz 或者 144Hz 的频率进行刷新 。而其中最常见的刷新频率是 60Hz 。
这样做是为了继承以前电视机刷新频率为 60Hz 的设定 。而 60Hz 是美国交流电的频率,电视机如果匹配交流电的刷新频率就可以有效的预防屏幕中出现滚动条,即互调失真 。
16 ms正如上面所述目前大多数显示器的刷新率是 60Hz,Android 设备的刷新率也是 60Hz 。只有当画面达到 60fps 时 App 应用才不会让用户感觉到卡顿 。那么 60fps 也就意味着 1000ms/60Hz = 16ms 。也就是说 16ms 渲染一次画面才不会卡顿 。
CPU vs GPU渲染操作通常依赖于两个核心组件:CPU 与 GPU 。CPU 负责包括 Measure、Layout、Record、Execute 的计算操作,GPU 负责 Rasterization (栅格化)操作 。
CPU 通常存在的问题的原因是存在非必需的视图组件,它不仅仅会带来重复的计算操作,而且还会占用额外的 GPU 资源 。
文章插图
CPU vs GPUAndroid UI 与 GPU
了解 Android 是如何利用 GPU 进行画面渲染有助于我们更好的理解性能问题 。
那么一个最实际的问题是:Activity 的画面是如何绘制到屏幕上的?那些复杂的 XML 布局文件又是如何能够被识别并绘制出来的?
文章插图
Resterization 栅格化是绘制那些 Button、Shape、Path、String、Bitmap 等组件最基础的操作 。它把那些组件拆分到不同的像素上进行显示 。
这是一个很费时的操作,GPU 的引入就是为了加快栅格化的操作 。
CPU 负责把 UI 组件计算成 Polygons,Texture 纹理,然后交给 GPU 进行栅格化渲染 。
文章插图
CPU 与 GPU 工作流程然而,每次从 CPU 转移到 GPU 是一件很麻烦的事情,所幸的是 OpenGL ES 可以把那些需要渲染的纹理缓存在 GPU Memory 里面,在下次需要渲染的时候可以直接使用 。但是,如果你更新了 GPU 缓存的纹理内容,那么之前保存的状态就丢失了 。
在 Android 里面那些由主题所提供的资源(例如:Bitmaps、Drawables)都是一起打包到统一的 Texture 纹理当中,然后再传递到GPU里面,这意味着每次你需要使用这些资源的时候,都是直接从纹理里面进行获取渲染的 。
当然,随着 UI 组件的越来越丰富,有了更多演变的形态 。例如,显示图片的时候,需要先经过 CPU 的计算加载到内存中,然后传递给 GPU 进行渲染 。文字的显示更加复杂,需要先经过 CPU 换算成纹理,然后再交给 GPU 进行渲染,回到 CPU 绘制单个字符的时候,再重新引用经过 GPU 渲染的内容 。动画则是一个更加复杂的操作流程 。
为了能够使得 App 流畅,我们需要在每一帧 16ms 以内处理完所有的 CPU 与 GPU 计算,绘制,渲染等等操作 。
UI 组件的更新通常来说,Android 需要把 XML 布局文件转换成 GPU 能够识别并绘制的对象 。这个操作是在 DisplayList 的帮助下完成的 。DisplayList 持有所有将要交给 GPU 绘制到屏幕上的数据信息 。
推荐阅读
- android6.0系统Healthd深入分析
- win10下搭建flutter android应用开发环境
- Android曝重大安全漏洞:允许攻击者录制视频、监听通话
- 如何在 Linux 中找出内存消耗最大的进程
- 深入理解 Android 9.0 Crash 机制 读懂底层原理 看清表面逻辑
- 几款实用的Android Studio 插件给你推荐一下
- Android Studio Debug 的 9 个小技巧
- android Flutter 工程结构和资源文件分辨率相关的图片文件放哪儿
- Android开发者,是时候了解LeakCanary了
- 11个促进Android应用开发的工具