Quartz2D的CALayer重绘存在的问题

iOS的视图绘制通常有三种方式,CoreGraphics、Quartz2D和OpenGL ES,性能从低到高。

CoreGraphics主要是覆盖UIView的drawRect的方式来实现视图绘制,而UIView的下层绘制是由CALayer提供的,UIView只是在CALayer上添加了事件捕获来响应用户交互操作。那么按道理说CoreGraphics与Quartz2D的性能差距应该不大,但事实并不是这样。

参考以下内容:
http://bihongbo.com/2016/01/03/memoryGhostdrawRect/
http://bihongbo.com/2016/01/11/memoryGhostMore/

可见如果drawRect使用不当,会造成大量的内存反复申请和释放(用来构建位图和刷新),而当该视图在不断变化,需要与屏幕有同样刷新率的情况下,这个性能是远远不足以达到的。这时候可以使用Quartz2D的一系列CALayer子类来实现。

新的问题

刚开始使用CAShapeLayer绘制图形的时候,还是蛮惊喜的,速度很快内存也几乎没有变化。但是不久后就发现了一个新问题。那就是在低端一些的机型上(其实也不是很低端,iPhone6p就会出现问题。而且即使是SE、6S、7等机型,如果重绘面积大、路径复杂,一样会出现同样的问题,只不过程度轻一些,应该是因为CPU性能的提升),如果视图内容是不断变化的,并且想以屏幕刷新率60fps一样的频率刷新视图内容,则会出现明显的丢帧卡顿现象,也就是说CAShapeLayer的重绘依然是一个很昂贵的操作,即使其矢量图的绘制方式在内存利用率上远远超过CoreGraphics的位图实现,但重绘机制依然是没有办法越过的障碍。

参考以下内容:
https://stackoverflow.com/questions/2720804/how-much-more-complex-is-it-to-draw-simple-curves-lines-and-circles-in-opengl-e/
https://stackoverflow.com/questions/2720642/what-is-faster-drawing-or-compositing/

I assume the reason you want to switch to OpenGL is to accelerate the animation of your drawn elements. In that question, you were attempting to animate by redrawing your UIView's contents with Quartz every frame. That will be incredibly slow, because of the way that the iPhone's drawing system works. Every frame, your view's backing layer would need to be converted to a texture and re-uploaded to the GPU, a very slow set of operations.

提问者的做法是尝试通过Quartz2D在每一帧重绘视图内容的方式来实现动画。但受限于iPhone的绘制系统工作机制,这个行为会极其的缓慢。因为每一帧内容都需要先被转换成纹理然后再重新上传GPU,这是一系列耗时操作。

Compositing is faster, by far. On the iPhone, content is drawn into a CALayer (or into a UIView's backing CALayer) using Quartz drawing calls or from a bitmapped image. This layer is then rasterized and effectively cached as an OpenGL texture on the GPU.

This drawing and caching operation is very expensive, but once the layer is on the GPU, it can be moved around, scaled, rotated, etc. in a hardware-accelerated manner. All the GPU has to do while the layer is animating is to composite it with the other onscreen layers every frame. This is why Core Animation can do 50 layers animating around the screen at 60 FPS on even the oldest iPhone models.

Layers and views only redraw themselves when prompted, or if resized when their needsDisplayOnBoundsChange property is set to YES. The drawing system is set up this way because of how expensive it is to redraw and recache the layer contents. If you can, avoid redrawing your layer content regularly, but instead split it into layers or views that you can animate around individually using Core Animation. If you need to animate a changing shape, look to CAShapeLayer, which makes this much more efficient than simply redrawing every frame.

目前混合比绘制快的多。在iPhone上,CALayer上的内容是通过Quartz绘制函数的调用或者通过一个位图图片绘制的。然后layer被栅格化然后作为OpenGL的纹理被高效缓存到GPU上。
绘制和缓存操作非常昂贵,但是一旦layer发送到了GPU上,就可以通过硬件加速的方式进行评议、缩放、旋转等变化。GPU在layer动画的过程中唯一需要做的就是在每一帧的时候把这个layer跟其他屏幕可见layer进行混合。这就是为什么Core Animation即使在最古老的iPhone机型上也能做到以60FPS的刷新率同时动画屏幕上的50个以上的layers。
layers和views只有接到通知的时候才进行重绘,另外如果needsDisplayOnBoundsChange被设置成true那么尺寸变化的时候也会重绘。之所以设计这种绘制系统就是因为重绘和缓存layer的内容十分消耗资源。应该尽可能的避免频繁重绘layer的内容,而是应该把内容切分到不同的layers或者views里面,然后独立对每个layer使用Core Animatio进行动画。如果需要动画一个变化的图形可以使用CAShapeLayer,这个比重绘每一帧高效的多。

结论

所以,当使用CALayer绘制产生性能问题的时候,就只能采用OpenGL ES了。总体来说的原则是,使用Quartz2D和Core Animation能解决需求并没有性能问题的情况下,优先使用它。若性能不满足则换OpenGL ES,没有什么理由来使用CoreGraphics,除非绘制任务很轻松没有太大区别(只绘制一次不刷新面积也很小的情况下)。

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

推荐阅读更多精彩内容

  • 本篇文章是基于谷歌有关Graphic的一篇概览文章的翻译:http://source.android.com/de...
    lee_3do阅读 7,113评论 2 21
  • 转载:http://www.jianshu.com/p/32fcadd12108 每个UIView有一个伙伴称为l...
    F麦子阅读 6,186评论 0 13
  • 有很多种framework以及很多种方法的组合可以在屏幕上渲染UI元素,我们在这里讨论这个过程中发生的事情,希望这...
    纵横而乐阅读 4,487评论 4 25
  • 在本系列上一篇《iOS 2D Graphic(1)—— Concept 基本概念和原理》中,我们已经了解了关于iO...
    ac3阅读 2,189评论 2 11
  • 那天老公被要求写一份详细的分析报告给领导,他在电脑前吭哧半天写出来一些,但总觉得不满意,交不了差。我也是觉得他一个...
    两个栗子阅读 296评论 2 8