The board does 2–3× less work per frame from 2,000 agents up, with no intended visual change. There are four parts:
- Feed and loop: pointer moves hit-test from a grid, a burst of live lines writes one stream row per frame, and a still board stops redrawing for its clock.
- Drawing: label widths are cached and label collision uses a 64 px cell index, off-screen work-group backgrounds are skipped, the background grid is a cached layer, and collapse membership is computed when something changes rather than walked per agent per frame.
- Layout: work nodes and agents live in spatial grids, so a tick stays near-linear. At 10,000 agents that is about 13,000 pair checks a frame instead of 20 million.
settle()stops after a 4 s budget, so a large board is placed in about 4 s instead of minutes, and keeps gathering in later frames. - Rank: each agent's rank and resting distance are cached alongside collapse membership. Only operator, provisioned and deleted events, and an agent's first scrobble, mark them dirty, which covers every input
collapses()andisHostread.
Frame time (median) from web/dev/bench/board.mjs in headless Chromium with software GL, so absolute numbers are pessimistic:
| agents | whole board | one household | close-up |
|---|---|---|---|
| 2,030 | 44.1 → 20.1 ms | 84.1 → 32.1 ms | 51.6 → 31.4 ms |
| 5,030 | 136.2 → 44.7 ms | 148.2 → 84.4 ms | 151.5 → 59.2 ms |
| 10,030 | 247.4 → 78.4 ms | 333.7 → 125.7 ms | 333.7 → 137.2 ms |
At 10,000 agents what remains is mostly layout.js:tick and step, then draw.js:collapses close in. A live board never rests, because births and deaths keep it warm. Letting settled agents sleep was tried and dropped, because the motion test requires a still board and a moving one to end in the same place.
All web tests pass apart from the two known failures, the shells test and the placeholder guard. web/dev/test/feed.test.mjs pins hover to a bounded number of agents at 5,000, draw-cull.test.mjs pins a zoomed-in frame to what is on screen, and layout.test.mjs pins pair checks per tick near-linear at 5,000. Node benchmarks for each part are in web/dev/bench/. The screenshots compare main and this branch at one household's zoom. The mock places nodes a little differently on each run, and the drawing is the same.
🤖 Generated with Claude Code