Ricky
Ricky

Reputation: 3171

Animation performance of hundreds of CALayers changes depending on hierarchy

I've been experiencing some difficulty in animating the opacity of a large amount (hundreds) of small CALayers. I was using Core Animation but went so far as to use CVDisplayLink to improve this.

What I've found is that having all these layers separate and animating their opacities produces extremely bad performance. In the display update code I would simply do:

for layer in layersToAnimateIn {
    layer.opacity = newOpacity
}

Moving all these layers into one bigger containing layer and animating its opacity seems to handle much better.

containingLayer.opacity = newOpacity

Since I'm dealing with the same amount of layers in each case, and the visual effect is identical, could someone explain why the performance changes so dramatically? The system obviously takes issue with me changing the opacity of hundreds of layers per screen refresh.

Upvotes: 0

Views: 105

Answers (1)

Noah Witherspoon
Noah Witherspoon

Reputation: 57139

There’s a performance cost to each change you make to the layer tree: the more layers you modify in one transaction, the more work CA has to do to go through and update its data model. If you’re changing everything to the same opacity, then the approach you’ve landed on is the right one—just change the opacity of the superlayer.

If you do need to set a bunch of layer properties to different values at once, make sure you’re disabling implicit animations—otherwise, you get an automatic animation for each changed property on each layer, which has a significant performance cost of its own. That’s especially important when you’re setting the property from a timer or a display link: if you set a property 30 times over the course of a second, you’re creating 30 animations in that time, which is… not good, to say the least. To disable implicit animations, wrap the code where you’re setting properties in a transaction, like this:

CATransaction.begin()
CATransaction.setDisableActions(true)
    for layer in layersToAnimateIn {
        // …
    }
CATransaction.commit()

Upvotes: 1

Related Questions