GPU 资源消耗原因和解决方案:
GPU能干的事情比较单一:接收提交的纹理Texture👌额顶点描述(三角形),应用变换(transform),混合并渲染,然后输出到屏幕上。通常你所能看到的内容,主要也就是纹理(图片)和形状(三角模拟的矢量图形)两类。
1:纹理的渲染:
所有的Bitmap,包括图片,文本,栅格化的内容,最终都要由内存提交到显存,绑定为GPU Texture。不论是提交到显存的过程,还是GPU调整和渲染Texture的过程,都要消耗不少GPU资源。当在较短时间显示大量图片时(比如TableView存在非常多的图片并且快速滑动时),CPU占用率很低,GPU占用率非常高,界面仍然会吊针。避免这种情况的方法只能是进行减少在短时间内大量图片的显示,尽可能将多张图片合为一张进行显示。
当图片过大,超过GPU的最大纹理尺寸时,图片需要先由CPU进行预处理,这对CPU和GPU都带来了额外的消耗。
2:视图的混合:
当多个视图(或者说CALayer)重叠在一起显示时,GPU会首先把他们混合在一起,如果视图结构过于复杂,混合的过程也会消耗很多GPU资源,为了减轻这种情况GPU消耗,应用应当尽量减少视图数量和层次,并在不透明的视图里标明opaque属性以避免无用的Alpha通道合成。
3:图形的生成:
CALayer的border,圆角,阴影,遮罩mask,CASharpLayer的矢量图形显示,通常会触发离屏渲染,而离屏渲染通常发生在GPU中,当一个列表视图中出现大量圆角的CALayer,并且快速滑动时,可以观察到GPU资源已经占满,而CPU资源消耗很少,这时界面仍然能正常滑动,但是平均帧数会降到很低。为了避免这种情况,可以尝试开启CALayer.shouldRasterize属性,但这会把原本离屏渲染的操作转嫁到CPU上去。对于只需要圆角的某些场合,也可以用一张已经绘制好的圆角图片覆盖到原本视图上面来模拟相同的视觉效果,最彻底的解决办法,就是把需要显示的图形在后台线程绘制为图片,避免使用圆角,阴影,遮罩等属性。