Why does yielding intermediate results makes this notebook much slower?

I’m working on a notebook that implements wave function collapse to build tiled grids. The version I have here is pretty rudimentary and not very optimized. To generate a 58x29 grid takes roughly 2 seconds on my computer.

I wanted to see how the algorithm progressed over time, so I started yielding intermediate results. I was very surprised when the overall runtime got 100 times slower! I batched updates so it wouldn’t yield every time, but even batch sizes of 100 (out of ~1600 total) were drastically slower.

I think that yield throttles the update speed of cells to match requestAnimationFrame. My intuition says that I should then target each of my updates to take about a frame to render. Assuming 60fps, that means I get 120 frames over the two seconds it takes to run as a one-shot. About 1600 steps on average tells me that each yield should process 10-15 steps. But with that setting the total runtime is about 20x slower.

I did all these tests in Firefox. In Chrome the situation is a little better, it’s only a 10x slowdown instead of 20x.

Am I missing something? Is there a better way to highlight intermediate algorithm results without slowing down the result?

PS: I tried using my browser profiling tools, and they pointed primarily to DOM updates. I tried adding Nanomorph to help with that, but it didn’t have a major impact.

1 Like

That would also have been my suspicion. If nanomorph updates an attached element then it will probably still trigger layout (which is expensive)?

You could try to

  • detach the parent element prior to updating the tiles, then reattach it
  • give render hints via will-change
  • switch to canvas

Do you have your nanomorph version published somewhere?

I don’t have the nanomorph version still. However, I thought about it more and realized that as well as the ~1600 elements apparent on the screen, there were another 1-4 per tile that hadn’t “settled” yet. That brought the total to above 6000 elements in the first few “frames” of the animation.

I stopped creating those debugging elements (which ironically was the reason I didn’t use canvas in the first place), and things got much much faster.

I also switched to using position: absolute and manual positions for my layout, which didn’t really help on it’s own.

1 Like