What's the best way to work around the findOne/findAll slowdown when encountering hidden layers?

I came across some interesting discussions around the performance of API recursive traversal methods like findOne and findAll, and I wanted to dig into deeper to figure out the best workaround given their behavior and the specific needs of our plugin.

Background:

In summary, it seems like traversal slows down significantly when encountering hidden layers, because Figma doesn’t instantiate invisible nested layers (since before variants released, files often contained tons of hidden layers as a workaround which quickly maxed out memory).

Here are the links to the discussions around this:

I’m assuming that means the hidden layers are stored as a reference and a slower lookup occurs when you access them in any way.

My question:

Our plugin doesn’t need to work with hidden layers, so I am wondering what the best workaround would be in this case. Is there additional info from Figma folks regarding how the uninstantiated hidden layers work under the hood that might be helpful?

Since Rudi at Figma (see last link above) said those layers aren’t instantiated at all, I’m thinking the hidden layers are stored as a reference and there’s no way to avoid the slowdown when using findOne/findAll on a node containing hidden layers, and the fastest workaround would be a custom recursive method that only handles a node and continues to recurse through its children if visible? Seems I’d still get the slowdown on the top hidden ancestor node, but I’d at least be able to avoid recursing through its children to skip all nested layers hidden within.

Does that sound reasonable to anyone here who has similar circumstances (no need to work with hidden layers anyway) and has experimented with this?

1 Like

I worked on this a lot (as you can imagine) and here are a couple notes:

  1. You are not entirely correct saying that traversing invisible nodes is slow. Traversing on itself isn’t slow at all. What’s slow is reading and writing different properties to objects within instances which contain invisible container nodes (no matter where in the tree these invisible nodes are).

  2. I wrote an extremely complex workaround for this which I can’t share, but a simple one could be ok as well: traverse the tree, save all invisible container nodes (frames, instances, groups, booleans, etc.) within instances to an array, make each in the array visible, then process the other nodes as you wish, then make all nodes in the array invisible again. The only issue is that this would create unnecessary visibility overrides in instances which you can’t reset via a plugin unfortunately.

1 Like

Thanks so much for your response, Gleb! (plus all the great info you provided in the discussions I linked!)

Thanks for clarifying on your point #1, that helps a ton.

As for the workaround, since we don’t need to do anything with hidden layers in our plugin, I’ve been tinkering with custom findOne/findAll functions that don’t continue recursing through children when encountering a hidden node, the hope being that at least skipping any nested layers that are hidden by proxy would save some time. Does that seem beneficial from your understanding of how hidden layers work, or could I be overlooking something?

Cutting out some nodes when traversing would definitely save some time, but you can’t do it with native functions. I summarized different ways of traversing the tree here: Figma layers tree traversal + estimating size - #4 by Gleb and while the default findAll is the fastest, if you are gonna skip some layers and do the search in the non-blocking way (by pausing the search occasionally), that could save some time and improve user experience.

1 Like