And*_*rea 48 rendering view layer ios
你好,
本周末我开始观看2011年WWDC视频.我发现了关于iOS的非常有趣的话题.我的最爱是关于性能和图形,但我发现其中两个显然是矛盾的.当然有一些我没有得到的东西.我正在谈论的会议是理解UIKit渲染-121和抛光你的应用程序-105.
不幸的是,2011年的示例代码仍然无法下载,因此很难获得整体视图.在一个会话中,他们解释说,在scrollview等可视化期间,大多数时候应该避免屏幕外渲染.他们修复了示例代码中的性能问题,几乎在-drawRect方法中绘制了所有内容.在另一个会话中,性能问题(在表视图上)似乎是由于表单元格的-drawRect方法中的代码过多.
首先我不清楚当系统需要OffScreen渲染时,我在视频中看到一些石英功能如:cornerRadious,shadowOffset,shadowColor需要它,但确实存在一般规则?
其次我不知道我是否理解得很好,但似乎没有屏幕外渲染添加图层或视图是要走的路.我希望有人能为此带来光明......
谢谢,
安德烈
Nic*_*ood 139
我不认为在任何地方写下了规则,但希望这会有所帮助:
首先,让我们澄清一些定义.我认为屏幕外渲染与屏幕渲染在大多数情况下都不是最重要的问题,因为屏幕外渲染可以像在屏幕上一样快.主要问题是渲染是在硬件还是软件中完成的.
使用图层和视图之间的实际差异也很小.视图只是CALayer的一个薄包装,它们在大多数情况下不会引入显着的性能损失.如果要使用CAShapeLayer或CATileLayer等支持的视图,可以使用+ layerClass方法覆盖视图使用的图层类型.
通常,在iOS上,像素效果和Quartz/Core Graphics绘图不是硬件加速的,而且大多数其他东西都是.
以下内容不是硬件加速,这意味着它们需要在软件中完成(屏幕外):
在drawRect中完成的任何事情.如果您的视图具有drawRect,即使是空视图,也不会在硬件中完成绘图,并且会降低性能.
将shouldRasterize属性设置为YES的任何图层.
任何带有蒙版或阴影的图层.
文本(任何类型,包括UILabels,CATextLayers,核心文本等).
您使用CGContext自己绘制的任何绘图(在屏幕上或屏幕外).
大多数其他东西都是硬件加速的,所以它们要快得多.但是,这可能并不意味着你的想法.
与硬件加速绘图相比,上述任何类型的绘图都很慢,但它们不一定会降低您的应用程序速度,因为它们不需要每帧都发生.例如,第一次在视图上绘制投影时速度很慢,但在绘制之后它会被缓存,并且只有在视图更改大小或形状时才会重绘.
对于使用自定义drawRect的光栅化视图或视图也是如此:视图通常不会每帧重绘,它被绘制一次然后缓存,因此首次设置视图后的性能不会更糟,除非边界更改或你在上面调用setNeedsDisplay.
为了获得良好的性能,诀窍是避免使用软件绘制来改变每一帧的视图.例如,如果您需要动画矢量形状,使用CAShapeLayer或OpenGL比使用drawRect和Core Graphics获得更好的性能.但是如果你画一次形状然后不需要改变它,它就没有太大的区别.
同样,不要在动画视图上放置投影,因为它会降低帧速率.但是视图上的阴影不会在帧与帧之间发生变化,不会产生太大的负面影响.
另外需要注意的是减慢视图设置时间.例如,假设您有一页文本,所有文本都有阴影; 这将需要很长时间才能绘制,因为文本和阴影都需要在软件中渲染,但一旦绘制它将会很快.因此,您需要在加载应用程序时提前设置此视图,并将其保留在内存中,以便用户不必等待视图在屏幕上首次显示时显示.
这可能是WWDC视频中明显矛盾的原因.对于不改变每个帧的大型复杂视图,在软件中绘制一次(之后将它们缓存并且不需要重新绘制)将比使硬件每帧重新组合它们产生更好的性能,即使第一次画画会慢一些.
但是对于必须不断重绘的视图,例如表格单元格(单元格被回收,因此每当一个单元格在屏幕外滚动并且在它作为不同的行向后滚动到另一侧时重新使用它们必须重新绘制),软件绘图可能放慢了很多东西.
小智 25
屏幕渲染是当今iOS渲染中最糟糕的主题之一.当Apple的UIKit工程师参考屏幕外渲染时,它具有非常特殊的含义,并且大量的第三方iOS开发博客都错了.
当您覆盖"drawRect:"时,您将通过CPU绘制并吐出位图.该位图被打包并发送到位于iOS(渲染服务器)中的单独进程.理想情况下,渲染服务器只是在屏幕上显示数据.
如果您在CALayer上使用属性,例如打开阴影,GPU将执行额外的绘制.这项额外的工作是UIKit工程师在说"屏幕外渲染"时的意思.这始终使用硬件执行.
离屏绘图的问题不一定是绘图.当GPU切换其绘图目的地时,屏幕外传递需要上下文切换.在此切换期间,GPU处于空闲状态.
虽然我不知道触发屏幕外传递的完整属性列表,但您可以使用Core Animation Instrument的"Color Offscreen-rendered layer"切换来诊断.我假设除了alpha之外的任何属性都是通过屏幕外传递来执行的.
对于早期的iOS硬件,可以说"在drawRect中做所有事情".现在GPU更好,UIKit具有像shouldRasterize这样的功能.今天,它是drawRect花费的时间,屏幕外通过的数量和混合量之间的平衡.有关完整的详细信息,请观看2014 WWDC会话419,"iOS应用的高级图形和动画".
总而言之,了解幕后发生的事情并将其保留在脑后,这样你就不会做任何疯狂事情,但你应该从最简单的解决方案开始.然后在您支持的最慢硬件上进行测试.如果您没有达到60FPS,请使用仪器测量并计算出来.存在一些可能的瓶颈,如果您不使用数据来诊断事物,那么您只是在猜测.
hfo*_*sli 11
图形性能的最大瓶颈是屏幕外渲染和混合 - 它们可能发生在动画的每一帧中,并且可能导致不连贯的滚动.
屏幕渲染(软件渲染)发生在需要在软件(屏幕外)进行绘图之前,可以将其移交给GPU.硬件不处理带有蒙版和阴影的文本渲染和高级合成.
以下内容将触发屏幕外渲染:
任何带面具的图层(layer.mask
)
任何具有layer.masksToBounds
/ view.clipsToBounds
为真的图层
任何layer.allowsGroupOpacity
设置为YES且layer.opacity
小于1.0的
图层视图(或图层)何时需要屏幕外渲染?
任何带阴影(layer.shadow*
)的图层.
有关如何修复的提示:https://markpospesel.wordpress.com/tag/performance/
任何一层layer.shouldRasterize
都是真的
任何一层layer.cornerRadius
,有layer.edgeAntialiasingMask
,layer.allowsEdgeAntialiasing
任何层与layer.borderWith
和layer.borderColor
?
缺少参考/证明
文本(任何一种,包括UILabel
,CATextLayer
,Core Text
等).
大多数你做拉伸的CGContext
在drawRect:
.即使是空的实现也会在屏幕外呈现.
这篇文章介绍了混合和影响性能的其他因素:什么触发了iOS中的屏幕外渲染,混合和layoutSubviews?