UIKit 性能优化(图层混合、光栅化、颜色格式、图片大小、离屏渲染)
图层混合
透明度设置为100%
如果某一块区域上覆盖了多个layer,最后的显示效果受到这些layer的共同影响。举个例子,上层是蓝色(RGB=0,0,1),透明度为50%,下层是红色(RGB=1,0,0)。那么最终的显示效果是紫色(RGB=0.5,0,0.5)。这种颜色的混合(blending)需要消耗一定的GPU资源,因为实际上可能不止只有两层。如果只想显示最上层的蓝色,可以把它的透明度设置为100%,这样GPU会忽略下面所有的layer,从而节约了很多不必要的运算。
UIImageView的图片也不能含有alpha通道
图像自身的性质可能会对结果有影响
设置 backgroundColor 属性(如果不设置背景颜色,控件依然会被认为是透明的)
虽然在白色背景下,无法肉眼看到效果,但重新调试后我们可以发现label的红色消失了。也正是因为对背景颜色的不重视,它成了影响滑动性能的第一个杀手。
如果label文字有中文,依然会出现图层混合,这是因为此时label多了一个sublayer
怎么解决。。
光栅化
光栅化是将一个layer预先渲染成位图(bitmap),然后加入缓存中。如果对于阴影效果这样比较消耗资源的静态内容进行缓存,可以得到一定幅度的性能提升
label.layer.shouldRasterize = true
因为layer进行光栅化后渲染成位图放在缓存中。
缓存中的对象有效期只有100ms,即如果在0.1s内没有被使用就会自动从缓存中清理出去。
光栅化的缓存机制是一把双刃剑,先写入缓存再读取有可能消耗较多的时间。因此光栅化仅适用于较复杂的、静态的效果。
光栅化会导致离屏渲染
颜色格式
像素在内存中的布局和它在磁盘中的存储方式并不相同。
当我们打开JPEG格式的图片时,CPU会进行一系列运算,将JPEG图片解压成像素数据。显然这个工作会消耗不少时间,所以不应该在滑动时进行,我们应该预先处理好图片。
Commit Transaction和Decode在同一帧内进行,如果这两个操作的耗时超过16.67s,Draw Calls就会延迟到下一帧,从而导致fps值的降低。下面是Commit Transaction的详细流程:
在第三步的Prepare中,CPU主要处理两件事:
把图片从PNG或JPEG等格式中解压出来,得到像素数据
如果GPU不支持这种颜色各式,CPU需要进行格式转换
使用instrument 的core animation 的 Color Copied Images检测图片格式
确保图片颜色格式能被GPU支持
图片大小
图片如果需要缩放会占用一定时间,确保图片大小与frame一致,不要在滑动的时候缩放图片
离屏渲染
离屏渲染会比普通渲染占用更多时间,以下几个会导致离屏渲染
- 重写drawRect方法
- 会导致大量内存消耗
有mask(layer.maskToBounds)或者是阴影(layer.shadow),模糊效果也是一种mask
//阴影效果可以指定阴影路径,否则core animation会去自动计算,就会触发离屏渲染 imgView.layer.shadowPath = UIBezierPath(rect: imgView.bounds).CGPath
layer.shouldRasterize = true
原文地址:UIKit性能调优实战讲解
参考链接:内存恶鬼drawRect