Why is -drawRect faster than using CALayers/UIViews for UITableViews?

后端 未结 3 1641
甜味超标
甜味超标 2021-02-06 15:07

I can already hear the wrenching guts of a thousand iOS developers.

No, I am not noob.

Why is -drawRect faster for UITableView performance than having mu

相关标签:
3条回答
  • 2021-02-06 15:39

    well, your program could easily end up moving and converting a lot of pixel data if going back and forth from GPU to CPU based renderers.

    as well, many layers can consume a lot of memory.

    0 讨论(0)
  • 2021-02-06 15:41

    When you talking about optimization, you need to provide specific situations and conditions and limitations. Because optimization is all about micro-management. Otherwise, it's meaningless.

    What's the basis of your faster? How did you measured it? What's the numbers?

    For example, no-op or very simple -drawRect: can be faster, but it doesn't mean it always does.

    I don't know internal design of CA neither. So here are my guesses.

    In case of static content

    It's weird that your drawing code is being called constantly. Because CALayer caches drawing result, and won't draw it again until you send setNeedsDisplay message. If you don't update cell's content, it's just same with single bitmap layer. Should be faster than multiple composited layers because it doesn't need composition cost. If you're using only small number of cells which are enough to be exist all in the pool at same time, it doesn't need to be updated. As RAM becomes larger in recent model, it's more likely to happen in recent models.

    In case of dynamic content

    If it is being updated constantly, it means you're actually updating them yourself. So maybe your layer-composited version would also being updated constantly. It means it is being composited again for every frame. It could be slower by how it is complex and large. If it's complex and large and have a lot of overlapping areas, it could be slower. I guess CA will draw everything strictly if it can't determine what area is fine to ignore. Unlike you can choose what to draw or not.

    In case of actual drawing is done in CPU

    Even you configure your view as pure composition of many layers, each sublayers should be drawn eventually. And drawing of their content is not guaranteed to be done in GPU. For example, I believe CATextLayer is drawing itself in CPU. (because drawing text with polygons on current mobile GPU doesn't make sense in performance perspective) And some filtering effects too. In that case, overall cost would be similar and plus it requires compositing cost.

    In case of well balanced load of CPU and GPU

    If your GPU is very busy for heavy load because there're too many layers or direct OpenGL drawings, your CPU may be idle. If your CG drawing can be done within the idle CPU time, it could be faster than giving more load to GPU.

    None of them is your case?

    If your case is none of situations I listed above, I really want to see and check the CG code draws faster than CA composition. I wish you attach some source code.

    0 讨论(0)
  • 2021-02-06 15:53

    I'm only seeing half the conversation here, so I might have misunderstood. Based on my recent experiences optimizing CALayer rendering, and investigating the ways Apple does(n't) optimize stuff you'd expect to be optimized...

    What's the difference if it all ends up cached and flattened anyway?

    Apple ends up creating a separate GPU element per layer. If you have lots of layers, you have lots of GPU elements. If you have one drawRect, you only have one element. Apple often does NOT flatten those, even where they could (and possibly "should").

    In many cases, "lots of elements" is no issue. But if they get to be large ... or there's enough of them ... or they're bad sizes for OpenGL ... AND (see below) they get stored in CPU instead of on GPU, then things start to get nasty. NB: in my experience:

    • "enough": 40+ in memory
    • "large": 100x100 points (200x200 retina pixels)

    Apple's code for GPU elements / buffers is well optimized in MOST places, but in a few places it's very POORLY optimized. The performance drop is like going off a cliff.

    Also, if you're handling cell reuse properly, you shouldn't need to regenerate views on each call to -cellForRowAtIndexPath

    You say "properly", except ... IIRC Apple's docs tell people not to do it that way, they go for a simpler approach (IMHO: weak docs), and instead re-populate all the subviews on every call. At which point ... how much are you saving?

    FINALLY:

    ...doesn't all this change with iOS 6, where the cost of creating a UIView is greatly reduced? (I haven't profiled it yet, just been hearing about it from other devs)

    0 讨论(0)
提交回复
热议问题