← the lab Hub

Demo 03

13s → 7.5ms

A card-arbitrage table had 516 rows. Clicking one to select it took 13 seconds. The cause was not the data, the filtering, or the machine — it was that selecting a row rebuilt every row, and read layout back from the DOM on each one. Below is the same bug and the same fix, reproduced here. Your browser does the timing.

516
5
Rebuild everything
ms

Regenerate all rows, then read layout back per row.

Touch what changed
ms

Two class changes, one layout read at the end.

Gap
×

Run it to find out what your machine does.

Live table — click any row 512 rows

What actually went wrong

The handler did the obvious thing: mark the clicked row as selected, then re-render the table so the highlight shows up. Re-rendering meant building all 516 rows again. That alone is O(N) work for an O(1) change, which is wasteful but survivable.

What made it 13 seconds instead of 30 milliseconds was the second mistake: each row's size was read back out of the layout engine immediately after it was written. Writing invalidates layout; reading forces it to be recomputed on the spot. Do both in a loop and the browser recalculates the whole document once per row — 516 full layout passes for one click.

The fix was not an optimisation. It was deleting work: stop rebuilding rows that did not change, and stop asking for layout inside the loop. The click went to 7.5 ms — flat, and no longer sensitive to row count.

Drag rows up and run it again. The red bar should grow with the row count — roughly quadratically, since the per-row cost also rises as the document gets bigger. The green bar should barely move: it does the same two class changes whether there are 64 rows or 2048.

An honest note on the numbers. The original 13.0 s → 7.5 ms was measured in a Python desktop UI, not in a browser, so the absolute figures here will not match — your machine, your engine, and a much lighter row are all different. What reproduces is the shape: an O(1) change priced as O(N), amplified by synchronous layout reads, and a fix that is subtraction rather than cleverness.