Offscreen rendering / Rendering on the CPU
The biggest bottlenecks to graphics performance are offscreen rendering and blending – they can happen for every frame of the animation and can cause choppy scrolling.
Offscreen rendering (software rendering) happens when it is necessary to do the drawing in software (offscreen) before it can be handed over to the GPU. Hardware does not handle text rendering and advanced compositions with masks and shadows.
The following will trigger offscreen rendering:
Any layer with a mask (layer.mask
)
Any layer with layer.masksToBounds
/ view.clipsToBounds
being true
Any layer with layer.allowsGroupOpacity
set to YES and layer.opacity
is less than 1.0
When does a view (or layer) require offscreen rendering?
Any layer with a drop shadow (layer.shadow*
).
Tips on how to fix: https://markpospesel.wordpress.com/tag/performance/
Any layer with layer.shouldRasterize
being true
Any layer with layer.cornerRadius
, layer.edgeAntialiasingMask
, layer.allowsEdgeAntialiasing
Any layer with layer.borderWith
and layer.borderColor
?
Missing reference / proof
Text (any kind, including UILabel
, CATextLayer
, Core Text
, etc).
Most of the drawings you do with CGContext
in drawRect:
. Even an empty implementation will be rendered offscreen.
Blending
resizableImage
can cause blending.
Avoiding blended layers when using resizableImages on iOS
Any layer which is not opaque
and has a backgroundColor
with alpha
less than 1.0
Any layer with alpha
less than 1.0
Any layer with layer.content
or any UIImageView
with a UIImage
having an alpha channel
Layout
The following things will trigger layoutSubviews
to be called on a UIView:
Changing bounds
triggers on the same view and superview
Changing frame
triggers on the same view and superview
Changing transform
or layer.transform
triggers on superview
Note: I'm referring to real changes where values actually are changing
Contradictory these changes does not trigger layoutSubviews
to be called: center
, layer.position
, layer.zPosition
, layer.anchorPoint
, layer.anchorPointZ
.
Reference: https://github.com/hfossli/LayoutSubviewsInconsistency
General tips for improving performance
Oftentimes it is better to blend
than to render offscreen
.
Consider using drawRect:
instead of having a view with multiple labels and subviews.
Draw on a background queue to a UIImage
or CGImageRef
.
Draw to a CGLayer
(which is cached better on GPU
compared to UIImage
), and draw whatever you want into it.
Update, don't: http://iosptl.com/posts/cglayer-no-longer-recommended/
Flatten your hierarchy
Reuse views – don't create and add new ones while scrolling
Have opaque
views with solid background color
Avoid setting alpha
and layer.opacity
to less than 1.0
Enable layer.shouldRasterize
(use with care). I like to avoid this personally, but it performs faster in some occasions since rasters of the layer will be cached and reused. Remember if you enable shouldRasterize
on layers that changing their content or sublayers contents frequently will cause the performance to drop, since iOS will keep rasterizing the layer on each change.
Links
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…