导读:
离屏渲染在开发中带来界面卡顿问题一直让开发者们头疼.今天在这里写一遍关于离屏渲染的博文.希望大家有所收获
现在的iOS开发越来越注重App性能和用户体验了.
性能优化和内存管理是iOS面试中必问的两道面试题.也是编程中最难的部分之一
要想知道如何解决界面卡顿问题,那你必须对离屏渲染有所了解
要想成为一个高级iOS程序员,你必须学会如何性能优化,内存优化
读懂了这篇文章,掌握离屏渲染的原理,让你的App从此远离卡顿.
OpenGL中,GPU屏幕渲染有以下两种方式:
一.On-Screen Rendering
意为当前屏幕渲染,指的是GPU的渲染操作是在当前用于显示的屏幕缓冲区中进行。
当前屏幕渲染是不需要额外创建新的缓存.也不需要开启新的上下文.相较与离屏渲染,性能更好.
但是受当前屏幕渲染的局限因素限制(只有自身上下文,屏幕缓存有限等),很对图形渲染,当前屏幕渲染是解决不了的.这时必须使用到离屏渲染.如何正确的使用离屏渲染,下面会为你详细描述
二.Off-Screen Rendering
意为离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。
特殊的“离屏渲染”:CPU渲染
如果我们重 写了drawRect方法,并且使用任何Core Graphics的技术进行了绘制操作,就涉及到了CPU渲染。整个渲染过程由CPU在App内同步地完成,渲染得到的bitmap(位图)最后再交由GPU用于 显示。
普通的离屏渲染
相比于当前屏幕渲染,离屏渲染的代价是很高的,主要体现在两个方面:
1.创建新缓冲区
要想进行离屏渲染,首先要创建一个新的缓冲区。
2.上下文切换
离屏渲染的整个过程,需要多次切换上下文环境:先是从当前屏幕(On-Screen)切换到离屏(Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上有需要将上下文环境从离屏切换到当前屏幕。而上下文环境的切换是要付出很大代价的。
设置了以下属性时,都会触发离屏绘制:
1.shouldRasterize(光栅化)
2.masks(遮罩)
3.shadows(阴影)
4.edge antialiasing(抗锯齿)
5.group opacity(不透明)
需要注意的是,如果shouldRasterize被设置成YES,在触发离屏绘制的同时,会将光栅化后的内容缓存起来,如果对应的layer及其sublayers没有发生改变,在下一帧的时候可以直接复用。这将在很大程度上提升渲染性能。
而其它属性如果是开启的,就不会有缓存,离屏绘制会在每一帧都发生。
在开发时需要根据实际情况来选择最优的实现方式,尽量使用On-Screen Rendering。简单的Off-Screen Rendering可以考虑使用Core Graphics让CPU来渲染。
如何抉择
现在摆在我们面前得有三个选择:当前屏幕渲染、离屏渲染、CPU渲染,该用哪个呢?这需要根据具体的使用场景来决定。
尽量使用当前屏幕渲染
鉴于离屏渲染、CPU渲染可能带来的性能问题,一般情况下,我们要尽量使用当前屏幕渲染。
离屏渲染 VS CPU渲染
由于GPU的浮点运算能力比CPU强,CPU渲染的效率可能不如离屏渲染;但如果仅仅是实现一个简单的效果,直接使用CPU渲染的效率又可能比离屏渲染好,毕竟普通的离屏渲染要涉及到缓冲区创建和上下文切换等耗时操作。普通的离屏绘制是发生在绘制服务(是独立的处理过程)并且同时通过GPU执行。当OpengGL的绘制程序在绘制每个layer的时候,有可能因为包含多子层级关系而必须停下来把他们合成到一个单独的缓存里。你可能认为GPU应该总是比CPU牛逼一点,但是在这里我们还是需要慎重的考虑一下。因为对GPU来说,从当前屏幕(on-screen)到离屏(off-screen)上下文环境的来回切换,代价是非常大的。因此对一些简单的绘制过程来说,这个过程有可能用CoreGraphics,全部用CPU来完成反而会比GPU做得更好。所以如果你正在尝试处理一些复杂的层级,并且在犹豫到底用-[CALayer setShouldRasterize:] 还是通过CoreGraphics来绘制层级上的所有内容,唯一的方法就是测试并且进行权衡。
总之,具体的选择应该由性能测试结果来决定。
简而言之:
如果觉得前面的过于抽象,没看懂,不要紧,把下面的看懂就能正确的解决离屏渲染带来的界面卡顿的问题了
1.尽量使用当前屏幕渲染,能不使用离屏渲染则尽量不用,你应当尽量避免使用 layer 的 border、corner、shadow、mask 等技术.
2.必须离屏渲染时,相对简单的视图应该使用cpu渲染,相对复杂的视图则使用一般的离屏渲染.