iOS view绘制性能

2017-07-26  本文已影响0人  只写BUG

视图显示到屏幕的过程:

CPU将显示的视图数据计算好,然后传给GPU渲染,渲染结束后,将数据传递给帧缓冲区,等待显示器绘制在屏幕上。
CPU计算:比如设置frame等,绘制一个layer
GPU渲染:将view的多个layer合成,再合成成像素的数据。GPU 能干的事情比较单一:接收提交的纹理(Texture)和顶点描述(三角形),应用变换(transform)、混合并渲染,生成bitmap.

iOS设置View到其显示在屏幕的过程,可以分成两个阶段:

App进程内:

渲染进程

影响绘制性能的关键问题

视图的frame计算都是需要cpu上计算的,所以视图层次越多越复杂多将消耗更多的cpu资源

GPU渲染两种方式

当前屏幕渲染:GPU的渲染操作用于当前的屏幕缓冲区
离屏渲染:指在GPU渲染之外开辟一个缓冲区,进行渲染操作。

只不过,将不在GPU缓冲渲染的操作都统称为离屏渲染:CPU渲染
比如常见重写drawRect操作就是离屏渲染方式。生成的bitmap传递给GPU用于显示。
设置以下属性的时候,都会触发离屏渲染
设置shouldRasterize(光栅化):每一个元素对应帧缓冲区中的一像素,用于缓冲相同的帧; masks,shadows;设置圆角,渐变等

比如:old = (100,100,100),v = (50,50,50),alpha = 0.5,那么new = (75,75,75)
如果太多计算的话,可能在1/60s内无法完成计算,就有可能出现掉帧的现象,掉帧到一定程度就可能出现屏幕卡顿的情况。

Demo

使用view来显示一个矩形,通过以下三种不同的方式来测试每种方法的代价,主要是内存消耗上考虑。

结果分析

每一个view实例,都默认管理着一个layer。UIView主要负责用户的交互,CALayer就是绘制图层属性和图形数据,用于视图的渲染。CALayer也具有层级关系,和UIView不同的是,它不知道响应链的存在。UIView其实是CALayer一层封装,让用户更加关注视图的处理逻辑,而不是视图的绘制逻辑,但是当你遇到性能问题的时候,你也不得不去了解更加深层的结构。
UIView实现了CALayer的CALayerDelegate,view视图的-drawRect方法背后其实调用了CALayer进行重绘和保存中间图片,当调用以下方法

  • (void)displayLayer:(CALayer *)layer;

回到实验部分,第一种方法,重写了drawRect,在数据准备阶段,生成该view的layer的contents的时候,需要在内存中view一样大的bitmap,并且这部分内存,只要view需要被显示在屏幕上,就一直不被释放。这就是实验中第一种方法,内存一直居高不下的原因。
第二种方法,内存先增加,是因为通过到创建core graphics 生成image,同样需要另外创建的内存,最后保留生成的bitmap在内存中.
最后一种方法,通过添加CAShapeLayer到view.layer的方法,其绘制图形的工作完全交由GPU来完成,所以不需要额外的内存。

参考:
https://objccn.io/issue-3-1/
http://www.jianshu.com/p/a1f575709e7c

上一篇 下一篇

猜你喜欢

热点阅读