我已经可以听到一千个iOS开发人员的痛苦。
不,我不是菜鸟。
为什么-drawRect对于UITableView性能比拥有多个视图更快?
我知道合成操作是在GPU上进行的。但合成是一次性的操作;一旦层被提交到内存,它与缓存的缓冲区没有区别,从GPU的角度来看,它被转换为视图内外。将此与在drawRect中使用Core Graphics进行比较,后者在CPU上使用未知数量的操作来生成最终在CALayers中缓存的像素。如果它最终都被缓存和扁平化有什么区别呢?
此外,如果您正确处理单元重用,则不需要在每次调用-cellForRowAtIndexPath时重新生成视图。实际上,使用UIView / CALayer对象缓存的状态数据(字体,字体大小,文本颜色,属性等)比在-drawRect期间不断重新创建它们可能有性能优势。
为什么drawRect的热潮?有人可以给我指点吗?
答案 0 :(得分:5)
当您谈论优化时,您需要提供特定情况和条件及限制。因为优化是关于微观管理的。否则,它毫无意义。
更快的基础是什么?你是怎么测量的?数字是多少?
例如,no-op或非常简单的-drawRect:
可以更快,但并不意味着它总是如此。
我不知道CA的内部设计。所以这是我的猜测。
你的绘图代码被不断调用很奇怪。因为CALayer
会缓存绘制结果,并且在您发送setNeedsDisplay
消息之前不会再次绘制结果。如果不更新单元格的内容,则它与单个位图图层相同。应该比多个合成图层更快,因为它不需要合成成本。如果您只使用足够小的单元格同时存在于池中,则不需要更新。随着RAM在最近的模型中变得越来越大,它更有可能发生在最近的模型中。
如果它不断更新,则表示您实际上正在自行更新它们。因此,您的图层合成版本也可能会不断更新。这意味着每个帧都会再次合成。它可能会因为复杂而庞大而变慢。如果它复杂而且很大并且有很多重叠区域,那么它可能会更慢。如果无法确定哪些区域可以忽略,我猜CA会严格绘制所有内容。不像你可以选择画什么。
即使您将视图配置为多层的纯组合,也应最终绘制每个子图层。并且不保证在GPU中绘制他们的内容。例如,我相信CATextLayer
正在吸引CPU。 (因为在当前移动GPU上绘制带有多边形的文本在性能方面没有意义)和一些过滤效果也是如此。在这种情况下,总体成本会相似,而且需要合成成本。
如果您的GPU非常繁忙,因为太多层或直接OpenGL绘图,您的CPU可能处于空闲状态。如果您的CG绘图可以在空闲的CPU时间内完成,那么它可能比为GPU提供更多负载更快。
如果你的情况不是我上面列出的情况,我真的很想看到并检查CG代码的绘制速度比CA组合快。我希望你附上一些源代码。
答案 1 :(得分:0)
好吧,如果从GPU到基于CPU的渲染器来回移动,您的程序很容易移动并转换大量像素数据。
同样,很多层都会占用大量内存。
答案 2 :(得分:0)
我只看到一半的谈话,所以我可能会误解。基于我最近优化CALayer渲染的经验,并研究Apple所做的(不)优化的方式,你希望优化它们......
如果它最终都被缓存和扁平化,那有什么区别呢?
Apple最终每层创建一个单独的GPU元素。如果你有很多层,你有很多GPU元素。如果你有一个drawRect,你只有一个元素。 Apple经常不会将它们弄平,即使它们可以(并且可能“应该”)。
在许多情况下,“很多元素”都没有问题。但是如果它们变得很大......或者它们已经足够......或者它们的OpenGL尺寸不合适......并且(见下文)它们存储在CPU而不是GPU中,那么事情开始变得讨厌。 NB:根据我的经验:
Apple的GPU元素/缓冲区代码在MOST中得到了很好的优化,但在一些地方它的优化程度非常低。表演下降就像走出悬崖一样。
此外,如果您正确处理细胞重用,则不需要 每次调用-cellForRowAtIndexPath
时重新生成视图
你说“正确”,除了...... IIRC Apple的文档告诉人们不要这样做,他们采用更简单的方法(恕我直言:弱文档),而是在每次调用时重新填充所有子视图。在那一点......你节省多少钱?
最后:
... iOS 6并没有改变所有这一切,创建UIView的成本大大降低了吗? (我还没有对它进行过分析,只是从其他开发者那里听说过)