iOS 性能优化 (一) 屏幕绘制原理

一.水平同步 垂直同步

(1)过去是CRT显示器,需要电子枪从上到下一行一行扫描,扫描完成后显示器就呈现一帧画面。完成一帧画面后,电子枪回到初始位置继续下一次扫描。
(2)当电子枪换到新的一行,准备进行扫描时,显示器会发出一个水平同步信号:HSync
(3)当一帧画面绘制完成后,电子枪回复到原位,准备画下一帧前,显示器会发出一个垂直同步信号: VSync
(4)显示器是固定频率,比如iOS 显示器是每秒60帧,16.6ms完成一帧

二. 缓冲区

iOS 性能优化 (一) 屏幕绘制原理_第1张图片
ios_screen_display.png

(1)CPU、GPU、显示器的工作原理如上图所示,CPU 计算好显示内容提交到 GPU,GPU 渲染完成后将渲染结果放入帧缓冲区,随后视频控制器会按照 VSync 信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示。
(2)为了解决效率问题,显示系统通常会引入两个缓冲区,GPU 会预先渲染好一帧放入一个缓冲区内,下一帧渲染完成后,收到VSync,指针指向下一个缓冲区。防止画面撕裂

三. 卡顿原因

iOS 性能优化 (一) 屏幕绘制原理_第2张图片
ios_frame_drop.png

(1)上图可以看到,每个VSync之间有时间间隔,iOS 设备上是16.6ms。在这个时间内,CPU主线程计算布局,解码图片,创建视图,绘制文本,计算完成后将内容交给GPU,GPU变换,合成,渲染(详细可学习 OpenGL相关课程),放入帧缓冲区
(2)假如16.6ms内,CPU和GPU没有来得及生产出一帧缓冲,那么这一帧会被丢弃,显示器就会保持不变,继续显示上一帧内容,这导致画面卡顿
(3)无论CPU,GPU,哪个消耗时间过长,都会导致在16.6ms内无法生成一帧缓存。

四.CPU 耗时操作(只说影响大的)

  1. Autolayout:自动布局,kuglerj进行过一些实验,一个比较复杂的页面,自定义代码 话费 120ms,自动布局 180ms,所以自动布局比代码布局多花费 50%时间,并且越复杂,子视图越多,时间是不成比例,近似指数增长的
    2.文本计算(宽高,位置):比如UILabel,文本是在主线程计算的
    3.文本渲染:所有文本内容控件,包括 UIWebView,排版和绘制都是在主线程进行的。当显示大量文本时,CPU 的压力会非常大
    4.图片的解码:当你用 UIImage 或 CGImageSource 的那几个方法创建图片时,图片数据并不会立刻解码。图片设置到 UIImageView 或者 CALayer.contents 中去,并且 CALayer 被提交到 GPU 前,CGImage 中的数据才会得到解码。这一步是发生在主线程的,并且不可避免。
    5.图像的绘制:生成bitmap

五.GPU耗时操作

1.纹理渲染:所有的 Bitmap,包括图片、文本、栅格化的内容,最终都要由内存提交到显存,绑定为 GPU Texture。不论是提交到显存的过程,还是 GPU 调整和渲染 Texture 的过程,都要消耗不少 GPU 资源。当在较短时间显示大量图片时(比如 TableView 存在非常多的图片并且快速滑动时),CPU 占用率很低,GPU 占用非常高,界面仍然会掉帧。
2.视图的混合(重点):视图混合,多个视图混合到一起时,会消耗大量gpu计算,应尽量避免alpha通道。alpha<1就会计算下一层视图,增加消耗资源alpha,多层视图
3.图形的生成(重点):CALayer的圆角,阴影,遮罩都会触发离屏渲染,快速滑动,CPU占用率少,GPU占用率非常高。可以开启calayer的光栅化,将离屏渲染转接到cpu上。

六:图片加载:对性能影响

1.从磁盘拷贝数据到内核缓冲区
2.从内核缓冲区复制数据到用户空间
3.生成UIImageView,把图像数据赋值给UIImageView
4.如果图像数据为未解码的PNG/JPG,解码为位图数据
5.CATransaction捕获到UIImageView layer树的变化
6.主线程Runloop提交CATransaction,开始进行图像渲染
6.1 如果数据没有字节对齐,Core Animation会再拷贝一份数据,进行字节对齐。
6.2 GPU处理位图数据,进行渲染。
参考文章:
iOS 保持界面流畅的技巧

你可能感兴趣的:(iOS 性能优化 (一) 屏幕绘制原理)