Files
jacuzzi/frontend/js/videos.js
Simon 6e5ab68a94 Prepare cards ahead of the scroll, and insert them in batches
DOM work cannot leave the main thread -- a worker has no document, and
nodes are not transferable -- so a card can never be compiled elsewhere.
It can be compiled *earlier*. The page already prefetches the next page's
JSON and warms its thumbnails; this does the same for the cards those
items will need, building and binding them while the browser is idle and
handing them over ready when the reader arrives.

Alongside that, three things that keep a frame from being held too long,
which is what smoothness actually reduces to when the work has nowhere
else to go:

Mounting and filling are drained against a 4ms budget rather than all at
once. Filling in one pass was a regression I introduced with the fling
deferral: it moved the stall from during the fling to the end of it.

A frame's mounts go into a DocumentFragment and enter the document in one
insertion, with filling afterwards so nothing reads layout mid-insert.

The pool is topped up with card shells during idle, so a mount during a
scroll is a rebind and not a construction: cards built mid-scroll fell
from 24 to 5 across profiling runs.

Also reverted, with its numbers kept in a comment: narrowing the overscan
during a fling. It reads like an obvious saving and measures as the
opposite -- a tight window makes cards leave and re-enter it, and mount
churn went from 88 to 155 with blocked time from 3.6s to 4.3s.

What this does not do is reduce total blocked time. Roughly three
quarters of it is browser style, layout, paint and decode for each card
shown, which no amount of scheduling removes. The deep stalls get
shorter; the thread stays busy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QBDkEXP4htyXTCZUwMLphd
2026-09-09 19:04:10 +00:00

108 KiB