设置CALayer的drawsAsynchronously未获性能提升,求排查方案
drawsAsynchronously没带来性能差异? 首先得明确CALayer.drawsAsynchronously的核心作用:它仅针对图层自身的异步绘制任务提交——也就是当图层需要重绘时,系统会把draw(in:)的执行(以及后续的Metal GPU渲染)放到后台队列,而非阻塞主队列。它并非对所有渲染路径都生效,你的三种测试场景恰好都不在它的覆盖范围内:
1. CAShapeLayer + render(in:)
CAShapeLayer本身就是Core Animation管理的GPU加速图层,它的路径渲染逻辑由系统直接通过Metal处理,完全不依赖drawsAsynchronously。而render(in:)是同步将图层内容渲染到指定CGContext的操作,这个过程是CPU主导的位图合成,和异步绘制机制无关,所以开关属性没影响。
2. UIGraphicsImageRenderer
UIGraphicsImageRenderer默认使用CPU端的Core Graphics上下文进行渲染,它的渲染路径独立于CALayer的绘制体系。drawsAsynchronously是CALayer的属性,无法影响这个工具的渲染逻辑,自然看不到性能差异。
3. UIView的draw(_:)
默认情况下,如果你是手动触发同步重绘(比如调用setNeedsDisplay()后立刻执行displayIfNeeded()),系统会强制在主队列完成绘制,不会触发异步逻辑。只有当系统自动调度重绘(比如视图布局变化、内容更新后由RunLoop触发的重绘),且图层的drawsAsynchronously = true时,才会把绘制任务放到后台队列执行。
让drawsAsynchronously生效的关键配置
要验证这个属性的性能提升,你需要调整测试场景到它的适用范围:
- 针对自定义CALayer:重写
draw(in:)方法,在里面添加足够复杂的绘制逻辑(比如大量贝塞尔路径、渐变填充、文字排版),设置layer.drawsAsynchronously = true,然后让系统自动触发重绘(比如修改图层内容后调用setNeedsDisplay(),等待RunLoop处理)。 - 针对UIView:
- 确保视图的
layer.drawsAsynchronously = true - 不要强制同步重绘,让系统在后台自动处理(比如避免在
setNeedsDisplay()后立刻调用displayIfNeeded()) - 绘制任务要有足够的复杂度(简单图形CPU处理足够快,体现不出GPU异步渲染的优势)
- 确保视图的
- 确认设备支持Metal(iOS 10+/macOS 10.12+,绝大多数现代设备都满足)
当满足这些条件时,异步绘制会把耗时的绘制任务从主队列转移到后台,同时利用Metal GPU加速渲染,才能看到明显的性能提升。
内容的提问来源于stack exchange,提问作者Jeshua Lacock

