MelonTeam 移动终端前沿技术的探索者

【特斯拉组件】跨线程渲染圆角图片

2017-03-27
ios

关于app的卡顿发生的原因,kM上相关的文章已经有很多了。有些文章已经分析得很深入,这里不再赘言。其本质原因是在一个VSync(垂直同步)时间片内(约等于1/60s,因为CADisplayLink的频率是1秒钟60次),App无法把一帧画面渲染到屏幕缓冲区,导致了掉帧。

一帧画面的数据通过总线经过 1,CPU的计算,再进入 2, GPU的渲染,最后被拷贝到屏幕缓冲区的,这两个过程都有可能导致屏幕掉帧:

CPU(主线程):

UI类相关的改动都必须在主线程完成,即使你用了Facebook的ASDK框架,最后也是要回到主线程提交相关的改动,所以任何堵塞主线程的操作,都可能引起掉帧。就看堵塞是发生在用户的代码还是堵塞在系统的lib里,常见的比如IO,长逻辑,死循环等等,都是比较容易发现然后解决的,比较难查的还是发生在系统库里的堵塞,经常发现用instrument去查看自己代码,基本不耗时,但是系统里的函数耗时却很长,比如自动布局的使用不当,就有可能引起这种问题。这里有两个大原则:

1 降低页面的复杂度。减少view的数目。就等于减少了布局计算,减少View的构建时间,减少View的销毁时间,而这些,通常都是发生了主线程的。

2 不要重复布局。 一个很明显的例子就是在tableviewcell里setFrame或者重新绑定自动布局,这会引起大量的布局计算。

3 尽量把逻辑放到后台线程。 图片编解码,网络,IO等等,能异步的就异步,网上很多的开源库,比如sdWebImage, fmdb等等,都是这个原理。

从作者度过的相关文章,基本上cpu的优化,都是从以上三个角度去优化程序的。

GPU:

GPU渲染比较复杂,涉及到的模块比较多,这里也不深入。主要讲讲离屏渲染,离屏渲染是什么呢?就是app在屏幕的硬件缓冲区外,自己开辟了缓冲区,进行图片的渲染,注意,硬件本身已经是双缓冲了,离屏渲染是硬件双缓冲之外的东西,当Layer设置了圆角,遮罩,阴影,transation等等,都会触发离屏渲染。可以简单理解一张需要离屏渲染的图片渲染成bitmap的性能是普通图片性能耗时的3倍,因为离屏渲染一般要经历三次渲染:

1 离屏渲染主图片

2 离屏渲染遮罩图片(比如,maskToBound)

3 主屏合成上述的两张图片

这里面可能会发生频繁的上下文切换,图片合成,是非常影响性能的。

好,下面进入正题,既然项目中带圆角的图片会严重影响tableview的性能,使用后台线程把矩形图片渲染成圆角图片既可以不卡主线程,又可以避免离屏渲染 ,节省GPU资源,大大提供性能。所以我们封装了一个圆角图片控件,实现借鉴了YYKit和参考了ASDK的思想,但是因为我们的项目大量使用了自动布局技术,所以我们没有直接使用第三方的控件,而是选择自己封装了一个。

优化前:(iPhone4, ios7, 26fps)

Alt text

优化后:(iPhone4, ios7, 60fps)

Alt text


说一说

目录