CPU 的任务繁多,做逻辑计算外,还要做内存管理、显示操作,因此在实际运算的时候性能会大打折扣,在没有 GPU 的时代,不能显示复杂的图形,其运算速度远跟不上今天复杂三维游戏的要求。即使 CPU的工作频率超过 2GHz 或更高,对它绘制图形提高也不大。这时 GPU的设计就出来了
CPU的主要工作是计算,将计算结果丢给GPU进行渲染
CPU和GPU的结构图如下所示
黄色的 Control 为控制器,用于协调控制整个 CPU 的运行,包括取出指令、控制其他模块的运行等;
绿色的 ALU ( Arithmetic Logic Unit )是算术逻辑单元,用于进行数学、逻辑运算;
橙色的 Cache 和 DRAM 分别为缓存和 RAM ,用于存储信息。
从结构图可以看出, CPU 的控制器较为复杂,而 ALU 数量较少。因此 CPU 擅长各种复杂的逻辑运算,但不擅长数学尤其是浮点运算。
简单介绍一个控件显示到界面上需要经过的步骤
xml文件
↓
通过LayoutInflater解析成对象加载到内存
↓
CPU处理成多维向量图像
↓
CPU 将向量图像交给 GPU,GPU 进行栅格化,然后绘制,负责像素填充。
UI对象
—-> CPU处理为多维图形,纹理
—–> 通过OpeGL ES接口调用GPU
—-> GPU对图进行光栅化(Frame Rate )
—-> 硬件时钟(Refresh Rate)
—-> 垂直同步
—-> 投射到屏幕
流程的图片流程
60Hz 刷新频率由来
12 fps :由于人类眼睛的特殊生理结构,如果所看画面之帧率高于每秒约 10-12 帧的时候,就会
认为是连贯的
24 fps :有声电影的拍摄及播放帧率均为每秒 24 帧,对一般人而言已算可接受
30 fps :早期的高动态电子游戏,帧率少于每秒 30 帧的话就会显得不连贯,这是因为没有动态模
糊使流畅度降低
60 fps 在与手机交互过程中,如触摸和反馈 60 帧以下人是能感觉出来的。 60 帧以上不能察觉
变化
当帧率低于 60 fps 时感觉的画面的卡顿和迟滞现象
Android系统每隔16ms发出VSYNC信号(1000ms/60=16.66ms),触发对UI进行渲染, 如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着计算渲染的大多数操作都必须在16ms内完成。
当这一帧画面渲染时间超过16ms的时候,垂直同步机制会让显示器硬件 等待GPU完成栅格化渲染操作,
这样会让这一帧画面,多停留了16ms,甚至更多.这样就这造成了 用户看起来 画面停顿.
当GPU渲染速度过慢,就会导致如下情况,某些帧显示的画面内容就会与上一帧的画面相同
16 毫秒的时间主要被两件事情所占用
第一件:将 UI 对象转换为一系列多边形和纹理( 1 )(?)
第二件: CPU 传递处理数据到 GPU 。所以很明显,我们要缩短这两部分的时间,也就是说需要尽量减少对象转换的次数,以及上传数据的次数 (? 布局 自定义)
如何减少这两部分的时间 以至于在 16ms 完成呢
GPU的绘制过程,就跟刷墙一样,一层层的进行,16ms刷一次.这样就会造成,图层覆盖的现象,即无用的图层还被绘制在底层,造成不必要的浪费.
GPU过度绘制的几种情况
自定义控件中,onDraw方法做了过多重复绘制
布局层次太深,重叠性太强,用户看不到的区域GPU也会渲染,导致耗时增加
那 Android 系统有没有给我们做优化的操作呢?
CPU 转移到 GPU 是一件很麻烦的事情,所幸的是 OpenGL ES 可以把那些需要渲染的纹理 Hold 在 GPU Memory 里面,在下次需要渲染的时候直接进行操作。所以如果你更新了 GPU 所 hold 住的纹理内容,那么之前保存的状态就丢失了。
在 Android 里面那些由主题所提供的资源,例如 Bitmaps , Drawables 都是一起打包到统一的 Texture 纹理当中,然后再传递到 GPU 里面,这意味着每次你需要使用这些资源的时候,都是直接从纹理里面进行获取渲染的。当然随着 UI 组件的越来越丰富,有了更多演变的形态。例如显示图片的时候,需要先经过 CPU 的计算加载到内存中,然后传递给 GPU 进行渲染。
文字的显示比较复杂,需要先经过 CPU 换算成纹理,然后交给 GPU 进行渲染,返回到 CPU 绘制单个字符的时候,再重新引用经过 GPU 渲染的内容。动画则存在一个更加复杂的操作流程。为了能够使得 App 流畅,我们需要在每帧 16ms 以内处理完所有的 CPU 与 GPU 的计算,绘制,渲染等等操作。
减少背景重复
主题中的设置
去掉单个activity的主题设置的属性,可以在setContentView之前调用getWindow().setBackgroundDrawable(null);
去掉所有activity主题设置中的属性直接在styles.xml中设置@null
使用裁减减少控件之间的重合部分
Android7.0之后系统做出的优化:invalidate()不再执行测量和布局动作
非业务需要,不要去设置背景
Android/sdk/tools/bin/ui automator viewer.bat
Android\sdk\tools\monitor.bat
Device Monitor窗口中Hierarchy view
我们可以借助一些工具来查看我们的布局层级。现在 Hierarchy Viewer 在 SDK 里找不到了,google 已经把它隐藏起来。并且 Hierarchy Viewer 只能在开发版手机或模拟器运行的限制。
Layout Inspector
现在 Android Studio 已经不支持 Hierarchy Viewer,也可以使用 Layout Inspector 进行替代查看布局
1.能在一个平面显示的内容,尽量只用一个容器
2.尽可能把相同的容器合并merge
3.能复用的代码,用include处理,可以减少GPU重复工作