卡顿

376 阅读3分钟

[参考文献]

参考链接

参考链接

参考链接

runloop卡顿监控demo

CPU

Layout:   布局位置,
Display:  绘制
Prepare: 图片的编码等
Commit: 提交

GPU

着色
图元装配
光栅化

在显示器中是固定的频率,比如iOS中是每秒60帧(60FPS),即每帧16.7ms 假如16.7ms内,CPU和GPU没有来得及生产出一帧缓冲,那么这一帧会被丢弃,显示器就会保持不变,继续显示上一帧内容,这就将导致导致画面卡顿

造成卡顿的原因

  1. 对象的创建,销毁都可以放到自线程
  2. 预排版,布局计算,为本计算等,都可以放到自线程中去。
  3. 预渲染,文本等异步绘制,图片编码等。
  • 离屏渲染,指图层在被显示之前是在当前屏幕缓冲区以外开辟的一个缓冲区进行渲染操作。 离屏渲染需要多次切换上下文环境:先是从当前屏幕(On-Screen)切换到离屏(Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上又需要将上下文环境从离屏切换到当前屏幕,而上下文环境的切换是一项高开销的动作。 例如:阴影,圆角,渐变。 阴影: 使用ShadowPath指定layer阴影效果路径。

  • 当多个视图(或者说 CALayer)重叠在一起显示时,GPU 会首先把他们混合到一起。如果视图结构过于复杂,混合的过程也会消耗很多 GPU 资源。

解决:应用应当尽量减少视图数量和层次,并且减少不必要的透明视图。

  • 短时间内大量的图片显示,CPU 占用率很低,GPU 占用非常高,界面仍然会掉帧。图片过大也会造成额外的消耗

解决: 减少段时间内大量的图片显示,尽可能多张图片合成一张显示。

  • heightForRowAtIndexPath 在tableView滑动时,会不断调用heightForRowAtIndexPath:,当 cell 高度需要自适应时,每次回调都要计算高度,会导致 UI 卡顿。为了避免重复无意义的计算,需要缓存高度。

  • opaque设置为YES,减少性能消耗,因为GPU将不会做任何合成,而是简单从这个层拷贝。 减少透明视图,blending主要指的是混合像素颜色的计算。最直观的例子就是,我们把两个图层叠加在一起,如果第一个图层的透明的,则最终像素的颜色计算需要将第二个图层也考虑进来。这一过程即为Blending。

  • 复杂图层避免是用 Autolayout 随着视图数量的增长,Autolayout 带来的 CPU 消耗会呈指数级上升。

异步绘制:

  • 假如说我们在某一个时机调用了[view setNeedsDisplay]这个方法,系统会在当前runloop将要结束的时候调用[CALyer display]方法,然后如果我们这个layer的代理实现了[view displayLayer]这个方法

  • 然后会通过子线程的切换,我们在子线程中去做一个位图的绘制,主线程可以去做一些其他的操作

  • 在子线程中第一步先通过CGBitmapContextCreate()方法来创建一个位图的上下文,然后我们通过CoreGraphic API可以做当前UI控件的一些绘制工作,最后我们再通过CGBitmapContextCreateImage()这个函数来根据当前所绘制的上下文来生成一张CGImage图片

  • 最后回到主线程来提交这个位图,设置layer的contents属性,这样就完成了一个UI控件的异步绘制过程