iOS性能优化 视图渲染

iOS性能优化的一个重要方面是视图渲染,在渲染的过程中避免出现图层混合,离屏渲染等问题,从而减少CPU和GPU的性能开销,达到性能优化的目的。

我们在开发调试过程中,可通过Xcode中的视图调试选项来帮助我们快速查找出渲染过程中的问题。
真机调试运行App项目,在Xcode的工具栏中选择,Debug -> View Debugging -> Rendering,其中有9个选项。

Xcode视图调试选项路径.png

若使用的是模拟器,在Simulator工具栏的Debug选栏中也有视图调试的选项。

Simulator视图调试选项路径.png
选项 说明
Color Blended Layers 图层混合,产生了图层混合视图上会标注为红色,没有发生图层混合视图上会标注为绿色。红色越多,性能越差。
Color Hit Green and Misses Red 光栅化,光栅化会将layer预先渲染成位图bitmap,然后被缓存,缓存未被复用则标注为红色,缓存被复用会标注为绿色。红色越多,性能越差。
Color Copied Images GPU 不支持的颜色格式的图片需要被复制到CPU进行颜色格式转换,因此这样的图片会被标注为蓝色。蓝色越多,性能越差。
Color Layer Formats 图层颜色格式, 暂不清楚。
Color Immediately 立即刷新, 通常以每10毫秒一次的频率更新图层调试颜色。选中这个选项则设置每帧画面都会刷新,在需要加快颜色刷新频率的场景下使用,通常情况下用不到。
Color Misaligned Images 图片错位,这个选项检查图片是否被缩放,以及像素是否对齐。被缩放的图片会被标记为黄色,像素不对齐则会标注为紫色。黄色、紫色越多,性能越差。
Color Offscreen-Rendered Yellow 离屏渲染,产生离屏渲染的图层会标注为黄色。黄色越多,性能越差。
Color Compositing Fast-Path Blue 快速路径,使用 OpenGL 绘制的图层会标注为蓝色。蓝色越多,性能越好。
Flash Updated Regions 重绘区域,进行了重绘的区域会标注成黄色,使用Core Graphics重新绘制会消耗性能,重绘区域越小越少,性能越好。

调试这几个选项,我们来具体看看,针对视图渲染有哪些具体问题需要优化。

Color Hit Green and Misses Red(图层混合)

在多个UI视图叠加的情况下,如果有透明或者半透明的控件,那么GPU会根据透明度去计算这些layer叠加在一起最终的显示的颜色。举例,如果顶层VeiwA颜色是红色RGB(255,0,0),透明度是40%,底层ViewB颜色是绿色RGB(0,255,0),那么最终叠加显示出来颜色是RGB(102,153,0)。
计算公式

RGB(混合) = RGB(A) * alpha + RGB(B) * (1-alpha)

这个渲染过程会消耗GPU性能,因此要避免出现图层混合。

  • 方法:去除透明度,给View添加alpha为1的背景色,这样在视图叠加时,因为没有了透明度,重叠部分直接按照顶层视图的颜色去显示。
    若视图是UIImageView,不仅需要自身这个容器的alpha为1,并且imageView包含的内容图片也是不透明的。

顺便提一下:UIView的opaque属性默认为Yes。
opaque这个属性不是决定视图是否透明,而是决定在视图渲染过程的处理方式。视图是否透明跟 alpha 和 hidden 有直接关系。
如果视图不透明,就设置opaque为Yes,表示图形系统会将视图视为完全不透明,完全不透明视图应该使用完全不透明的内容来填充,该内容的alpha值应该为1.0(自身的alpha和填充颜色的alpha都应该为1.0),这样图形系统将不考虑它与其他视图的混合颜色计算,从而提高性能。若设置为NO,图形系统通常会将视图与其他内容合成,消耗性能。如果View是在scrollView中或者在动画中,对性能的提升更为明显。
有些View的子类使用drawRect:方法绘制自己的内容,那么opaque属性对其无效。

Color Hit Green and Misses Red(光栅化)

这个选项用来检测是否正确使用layer的shouldRasterize属性,该属性默认是NO,若 shouldRasterize为YES则开启光栅化。光栅化是将layer预先渲染成位图(bitmap),然后缓存起来,缓存未被复用则标注为红色,缓存被复用会标注为绿色,红色越多,性能越差。使用光栅化的视图清晰度会降低。

  • 对于不是频繁绘制的静态视图,若需要添加阴影、圆角等,进行光栅化处理,会对性能有提升。
  • 对于会频繁绘制的视图,如tableViewCell,一般不要使用光栅化,开启光栅化就会产生离屏渲染,因为光栅化的缓存就是当前屏幕缓冲区以外新开辟缓冲区。由于tableViewCell的绘制非常频繁,内容在不断的变化,会不断的产生缓存,造成大量的离屏渲染降低性能。缓存的保留时间为100ms,如果在100ms内没有使用缓存的对象,则会将缓存释放。正因如此,会出现下面的现象。 若在tableViewCell中开启光栅化,刚进入页面时, 所有使用了光栅化的视图layer都标注为红色,因为虽进行了光栅化缓存,但是没有被复用;在滑动tableView时,若滑动幅度比较小,没有新的视图出现,那么光栅化缓存被复用,所有视图的layer都标注为绿色。随着滑动幅度变大,新的视图出现,新视图的光栅化缓存被创建,但是没有被复用,就会被标注为红色,但是光栅化缓存的保留时间为100ms,新视图标注的红色就会变为绿色。
    光栅化的使用有利有弊,正确的使用光栅化可以得到一定程度的性能提升。

Color Copied Images (图片被复制)

苹果的GPU只解析32bit的颜色格式,32bit的颜色格式由RGBA(红、绿、蓝、透明度)四个颜色通道组成,每一个颜色通道都占据8bit,取值范围是[0, 255]。
如果某图片是GPU 不支持的颜色格式,那么图片需要被复制到CPU进行颜色格式转换,这样的图片会被标注为蓝色。蓝色越多,性能越差。

Color Layer Formats(图层颜色格式)

这个选项用来解析图层的颜色格式,具体用途暂不清楚。
打开这个选项后,UILabel都会被标注,标注为银白色或橙色,UIImageView的图片内容有部分透明时标注为紫罗兰色,全不透明时标注为橙色;有趣的是,xib中调整UILabel的textColor,当RGB三个颜色通道的色值一致时(如000000、999999、FFFFFF等),UILabel会被标注为银白色,当RGB三个颜色通道的色值不一样时(如999897等),UILabel会被标注为橙色。

Color Immediately(颜色刷新)

这个选项用来调整颜色刷新频率。通常情况是以每10毫秒一次的频率更新图层调试颜色,选中这个选项则设置每帧画面都会刷新,没有了10毫秒的延迟。在需要加快颜色刷新频率的场景下使用,通常情况下用不到。

Color Misaligned Images(图片错位)

这个选项用来检测图片在展示时是否被放大或缩小,以及像素是否对齐。如果image.size和imageView.size不匹配(例如,image的实际大小是50×50,imageView的尺寸大小25×25,或者为200×200),图片在展示时会缩放或者放大图片,会消耗资源,imageView会被标注为黄色,黄色越多,性能越差。避免出现黄色标注,将imageView.size设置成与image.size一样的。

Color Offscreen-Rendered Yellow(离屏渲染)

这个选项用来检测是会把那些离屏渲染的图层显示为黄色。黄色越多,性能越差。

屏幕渲染有 当前屏幕渲染 和 离屏渲染 两种方式。

  • 当前屏幕渲染(On-Screen Rendering):GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。
  • 离屏渲染(Off-Screen Rendering):GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。离屏渲染会先在屏幕外创建新缓冲区,离屏渲染结束后,再从离屏切到当前屏幕, 把离屏的渲染结果显示到当前屏幕上,这个上下文切换的过程很消耗性能,开发中应尽可能避免离屏渲染。

常见的会引起离屏渲染的操作:

  • shadows(阴影):在设置阴影属性时,一定要指定阴影路径,可以避免离屏渲染。
view.layer.shadowOffset = CGSizeMake(0, 2);
view.layer.shadowOpacity = 1;
view.layer.shadowRadius = 4;
view.layer.shadowPath = CGPathCreateWithRect(view.bounds, nil);
//或者
view.layer.shadowPath =UIBezierPath(view.bounds).CGPath;
  • shouldRasterize(光栅化):上面有提到过,开启光栅化就会产生离屏渲染,因为光栅化的缓存就是当前屏幕缓冲区以外新开辟缓冲区。虽然会产生离屏渲染,但是不代表就一定会降低性能。若页面初始创建视图时,很多视图需要设置圆角,阴影,遮罩等属性,一下子处理这些需要图层混合的渲染,很消耗性能,但是开启光栅化,相同的效果只被渲染了一次,然后一直在缓存中被复用,减少了整个渲染的频度和时间,从而提升性能。总之,视情况而定,采用最优的方式来优化性能。

  • masks(遮罩):单独设置layer.cornerRadius,或者设置layer.masksToBounds为Yes,并不会引起离屏渲染,但是同时设置这两个属性会引起离屏渲染。
    设置圆角:
    1.使用带圆角的图片,这样最直接。
    2.iOS11之后,通常设置layer.maskedCorners和layer.cornerRadius,再加上背景色可以了,在设置背景色时,UILabel或者UITextView不要设置backgroundColor,而是设置layer.backgroundColor。

    label.layer.cornerRadius = 10;
    label.layer.backgroundColor = [UIColor redColor].CGColor;
    

    3.通过CAShapeLayer,将绘制有圆角的layer赋值给layer.mask。该方法会引起离屏渲染。
    4.通过混合图层的方式,在需要添加圆角的视图上再叠加一个部分透明的视图,只对圆角部分进行遮挡,叠加后达到有圆角的效果。多一个图层会增加的工作量与离屏渲染相比微不足道。

Color Compositing Fast-Path Blue(快速路径)

这个选项用来检测是否是直接使用 OpenGL 绘制的, 使用 OpenGL 绘制的图层会标注为蓝色。蓝色越多,性能越好。如果仅仅使用 UIKitAPI,那么不会有任何效果。

Flash Updated Regions(重绘区域)

这个选项用来检测是否出现重新绘制,进行了重绘的区域会标注成黄色,使用Core Graphics重新绘制会消耗性能,因此重绘区域越小越少,性能越好。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容