Dress Up reports · ^du_report(2) · 2026-10-16 · about Messed Up Dress Up, a game made with M and N · after ^du_report(1)
The kids' computers
Why was Messed Up Dress Up choppy on an Ubuntu laptop (Intel i7) and on an iPad, and pausing on Matthew's laptop, and what made it smooth? The evening of 2026-10-16, from 0.0.80 to 0.0.93, measured on each computer with the game's own 🧪 and carried back by hand.
Short answers. Each computer's figures are one run of the game's own 🧪 this computer's speed on it (below): each pass is 2 seconds of frames, so a few frames a second either way is noise.
- Smooth now: the duck pond swims at 58 frames a second on the Ubuntu laptop (27 as it is) and 60 on the iPad (22), with the place drawn as still bitmaps while the friend moves (🧪 on 0.0.92, pass 10: the pictures 0.0.93 draws). 0.0.93 turns them on by itself once it finds a computer choppy, after about 4 to 6 seconds of moving in a busy place.
- Two computers, two causes. On the Ubuntu laptop (Intel i7), in Firefox 136, the cost is the places' animations (the pond has 57): held still, the pond swims at 58. On the iPad (Safari) it is the scenery's shapes, drawn again every frame: held still 25, as an svg picture 24 (Safari, it seems, draws even a picture made of svg again every frame), as a bitmap 60.
- Matthew's laptop paused because of a stale mark. Found choppy once, the mark was kept in the browser: every place was held still on every visit since, and the still pictures were built on every arrival, though its 🧪 ran every pass at 57 to 61 (0.0.91). Measured afresh on each visit since 0.0.92: "the pauses are gone".
- Only the computers themselves could tell. Nothing we ran on Matthew's laptop reproduced the kids' computers: headless Chrome slowed down 2 times swam the pond at 55.7 where the Ubuntu laptop managed 36, headless Firefox at the Ubuntu laptop's screen at 60, and the trips that paused in Matthew's Firefox ran at 59 to 60 in both headless browsers. The numbers came from each computer, pasted into a public page.
2026-10-16, later that night: ^du_report(3) found a cost of the game's own script after all: not its drawing (1.0 ms, as above) but the 🏞️ Background tab's refresh of its controls while the friend moves, which held the duck pond to 2.4 to 14.9 frames a second whenever that tab was open, until a reload. 🧪 never ran with that tab open, and a headless browser on GitHub's computers showed it at once: a stand-in that could tell, for this kind of cost.
Where it stands
Every 🧪 pass on the three computers on 0.0.92, frames a second with the share of frames later than 25 ms. Green is 55 or more, the gate's bar (^du_report(1)). "Pictures" is the share of the friend's drawings that had the still pictures on. A drawing of the friend takes 1.0 ms on all three: the game's own work is never the cost.
| 🧪 pass, on 0.0.92 | Ubuntu, Intel i7 | the iPad | Matthew's laptop |
|---|---|---|---|
| a drawing (ms) | 1 | 1 | 1 |
| empty room, walking | 58 (2% late) | 44 (6% late) | 60 (1% late) |
| duck pond, swimming | 27 (93% late) | 22 (100% late) | 61 (0% late) |
| held still | 58 (2% late) | 25 (100% late) | 60 (1% late) |
| without its scenery | 59 (0% late) | 47 (3% late) | 60 (0% late) |
| without the part under water | 34 (72% late) | 25 (100% late) | 60 (0% late) |
| without the rings | 34 (67% late) | 24 (100% late) | 60 (0% late) |
| without both | 37 (59% late) | 25 (100% late) | 60 (0% late) |
| still pictures, svg | 59 (0% late) pictures 99% | 24 (100% late) pictures 99% | 60 (0% late) pictures 0% |
| still pictures, bitmaps | 58 (1% late) pictures 100% | 60 (0% late) pictures 99% | 61 (1% late) pictures 0% |
| with music | 29 (90% late) | 22 (100% late) | 61 (1% late) |
| the empty room after the pond | 57 (2% late) | 60 (0% late) | 60 (0% late) |
Bitmaps are what 0.0.93 draws by itself on a computer it finds choppy. A fast computer, such as Matthew's, is never found choppy and draws every place as it is, moving. Matthew's line came from 0.0.92 before its release (from the working copy), before 🧪's own fix was folded into it: there the held-still and picture passes did not hold still (pictures 0%; below).
Two causes
The Ubuntu laptop pays for the animations. Held still (its 57 animations stopped: the five ducks swimming, ripples spreading and fading on the water, and the scenery's other small movements), the pond swims at 58, as it does without its scenery at all (59). The rings round the friend and their faint part under the water cost a little (27 → 37 without both) but not most. As far as we can tell, Firefox paints the picture again wherever anything in it moves, and in the pond something always does.
The iPad pays for the shapes. Held still, the pond swims at 25: there, the animations were never the cost. Without its scenery, 47. Drawn as one still picture made of svg, still 24: it seems Safari draws a picture made of svg again every frame, as if it were the scene itself. Drawn once into pixels, a bitmap, 60.
Bitmaps answer both, 58 and 60, so since 0.0.93 the still pictures are bitmaps everywhere: each part of the place (cut where the friend stands in it, so they still pass behind what stands nearer) drawn once into a canvas at the picture's own size on the screen, and made again if that size changes. A computer is found choppy in windows of 60 frames now (120 before), so the iPad gets them after about 5½ seconds of swimming, not 11, and the Ubuntu laptop after about 4½.
How it got here
From 15:01, when 0.0.80 was too slow everywhere on the Ubuntu laptop, even in the empty room, to 0.0.93 at 19:33. The releases on the way that bear on speed (the evening's others added doors, walls and pits: 0.0.88 to 0.0.90):
| version | commit | what changed |
|---|---|---|
| 0.0.81 | c8af960 | A step of movement only draws; on a slow computer, at most 30 drawings a second while moving. |
| 0.0.82 | d7fae25 | 🧪 this computer's speed: a line to compare computers by. |
| 0.0.83 | 858f369 | On a slow computer (drawing over 6 ms) the places held still: their animations taken out. |
| 0.0.84 | 151085a | Also held still where moves come out choppy (frames late while moving), as the Ubuntu laptop's did though it draws in 1 ms. |
| 0.0.86 | c49d6f2 | 🧪 takes the duck pond apart: the pond without one part at a time, and the empty room after the pond. |
| 0.0.87 | 431d897 | On a slow computer, while the friend moves, the place drawn as still pictures (svg), cut where the friend goes. |
| 0.0.91 | 51f13e1 | ⏱️ time the next trip: every frame of a trip through a doorway, its phase, the game's share. |
| 0.0.92 | 119c5c6 | "Choppy" measured afresh each visit and on stronger evidence; 🧪's held-still passes really held still. |
| 0.0.93 | eebaa60 | The still pictures as bitmaps; choppy found in windows of 60 frames, not 120. |
Matthew's laptop: the pauses
After 0.0.90, Matthew found the game slow on his own laptop, with pauses going through a castle door and into a pit, by a click and by walking onto one. We timed those four trips, frame by frame, in both headless browsers on the same laptop, at its own size (1203×802 at 1.875×), normally and as a computer found choppy:
| trip (0.0.90) | Chrome | Chrome, as choppy | Firefox | Firefox, as choppy |
|---|---|---|---|---|
| outside the castle, through its gate | 60 fps | 59 fps | 59 fps | 60 fps; 34 ms arriving |
| a hallway's wooden door (it swings) | 59 fps; 50 ms arriving | 59 fps; 50 ms arriving, 67 ms the next frame | 59 fps; 50 ms arriving (the browser) | 59 fps; 83 ms arriving |
| a pit, clicked | 60 fps | 60 fps | 60 fps | 59 fps; 50 ms walking |
| a pit, walked onto | 60 fps | 60 fps | 59 fps; 50 ms before the press (the browser) | 60 fps |
No pauses. The only long frames are where the new place is built and first painted (34 to 83 ms, the game's part of them 13 to 16 ms). So the pauses were not the game's script, and headless browsers could not show the painting in a window. 0.0.91 added ⏱️ time the next trip (⚙️ Advanced), to time a trip on the laptop itself.
The answer came before the timer was needed. Matthew's 🧪 line on 0.0.91 said "found": {"slow": false, "choppy": true}, with every pass at 57 to 61. The mark, kept in the browser since 0.0.84 so that a slow computer would not flip back and forth, had been set once, perhaps while something heavy ran alongside, and stayed. It held every place still on every visit after, and it made 0.0.87's still pictures (svg then: the whole place copied, serialized and decoded) be built on every arrival somewhere new.
0.0.92 measures it afresh on each visit (the old mark is cleared on load), only on stronger evidence (more than a quarter of the frames late in two windows in a row: the Ubuntu laptop's pond passes were 62 to 93% late, Matthew's worst pass 9%), and not during a trip, whose arrival is a long frame by nature. Tested with frames made late on purpose (the page kept busy in each frame, the drawing itself fast): never marked at full speed or 12 ms late a frame; marked after about 8 seconds at 30 ms late (about 4 since 0.0.93's shorter windows). On 0.0.92, Matthew: "the pauses are gone".
What our stand-ins could not show
We tried to reproduce the kids' computers on Matthew's laptop first, as is cheaper, and could not:
- Headless Chrome slowed down (its CPU throttled 2 times, the Ubuntu laptop's drawing measured against it): the pond at 55.7, where the Ubuntu laptop swam at 36 (0.0.84).
- Headless Firefox (157, at the Ubuntu laptop's screen, 1440×810 at 2×): 60 in every pass.
- The trips that paused in Matthew's Firefox window: 59 to 60 in both (above).
Slowing the CPU slows the game's own script, which was never the cost (1.0 ms a drawing on every computer), and a headless browser does not paint as a window on a screen does. The costs were the painting's, and each browser's own (Firefox's with animations, Safari's with shapes): only the computers themselves could show them. So 🧪 grew passes that take one part away at a time, and its lines were carried back from each computer.
What we got wrong on the way
🧪's "held still" never held still, until 0.0.92. The pass marked the computer slow for its 2 seconds, but the game measures its drawing after every frame and takes the mark back when drawing is fast (under 2.5 ms on average): on the Ubuntu laptop, after one frame. So the Ubuntu laptop's "held still" (33 on 0.0.84, 31 on 0.0.86) was the pond moving, and we wrote down that holding still did not help there. It does: 58 (0.0.92). The passes now hold still with a switch of their own. (The iPad's 0.0.86 line was right: it was marked choppy then, which held the pond still anyway.)
The first still pictures drew some scenery under the things standing in front of it (0.0.87, before release): the castle's path below the bridge, a tree house room's door frame. Every standing thing was kept live over one picture of all the rest, but some of the rest is drawn after them. A pixel comparison of every place, the picture against the scene itself, caught it (0.64% and 0.61% of the pixels apart, against 0.0 to 0.3 elsewhere); the pictures are now cut where the friend goes in the drawing order, things and all.
The choppy mark was kept forever (0.0.84 to 0.0.91), as told above.
Our own checks lost their footing when 0.0.92 cleared kept marks on load: they had set the mark through the browser's storage, so they quietly checked no pictures at all, until a check showed none drawn. They set it in the page now.
🧪 waited 4 seconds in each pass (0.0.87 to 0.0.92) for a value the 0.0.87 rework had removed.
How the measurements were gathered
On each computer, the game's ⚙️ Advanced tab: 🧪 this computer's speed (about 40 seconds) or ⏱️ time the next trip, then 📋 copy, then 📝 then paste it here, which opens a shared page: a Riseup pad. We read it back from that page's plain-text export. The Ubuntu laptop has no easy way to reach Claude or Matthew's usual accounts, by design; a page that anyone can open was the bridge (0.0.83).
What a line carries: the version, each pass's frames, the browser and its version, the platform, the screen's size and pixel ratio, the number of processor cores, the picture's size, and the computer's marks. Nothing typed, no names, no accounts. But together, screen, pixel ratio, cores and browser narrow down a device more than they need to.
Its limits: the pad is public (its address is in the game's public source, and anyone with it can read and change it), carried by hand (one line at a time, by whoever holds the computer), and short-lived (deleted after 60 days with no edits). This report keeps a copy of the evening's lines (data/pad-2026-10-16.txt).
What we'd rather: a canister of our own
We would rather gather these lines with a canister we control (ticket 166): telemetry that keeps people's privacy and that they go on choosing to give. What we would want of it, for a later report to test:
- Opt-in, every time. Nothing leaves the game unless someone presses the button, as now; nothing is sent in the background.
- Seen before sent. The line shown is exactly what is sent, no more.
- Less in each line. Sizes rounded, the browser's version to its major number; no identifier, no account, no address kept with a line.
- Readable by us, for reports; deletable. Old lines expire; a line can be taken back by whoever sent it, with a key kept only in their own browser.
- Hard to flood. A limit on lines per minute.
Open questions, for Matthew: where it runs (the IC's main network costs cycles, paid from his identity; a local replica would not reach the Ubuntu laptop), and who may write to it (anyone with the game, as the pad now, or only the game itself).
What next
- 1. Run 🧪 on each kids' computer on 0.0.93, to see the bitmaps turn on by themselves: swim in the pond a few seconds first, then the duck pond pass should read near 60 (ticket 164).
- 2. ⏱️ time trips on the kids' computers (a castle door, a pit), now that their places move smoothly: what is left is where a new place is built and first painted.
- 3. Decide where the telemetry canister runs and who may write to it, then build its send beside 📋, opt-in and seen before sent (ticket 166).
- 4. Try a Safari stand-in on the laptop: WebKit's own build for Linux at the iPad's size, to see whether it shows the iPad's 24 against 60; if it does, a case for it in the frame-rate gate.
- 5. The audit of every place with the on-screen controller (ticket 160), and the checks into CI (ticket 165).
How this was put together
🧪 this computer's speed is part of the game (⚙️ Advanced). It draws the friend 60 times and takes the median time of a drawing, then runs 14 passes of 2 seconds each: walking across the empty room, standing in place, swimming across the duck pond (moving; held still; without its scenery; without the friend's part under the water; without the rings; without both; as still pictures, svg; as still pictures, bitmaps; with its music), and the empty room again after the pond, then with its music (12 passes in 0.0.86, 14 since 0.0.87). The friend is moved by the game's own controller step; frames are counted with requestAnimationFrame; frames a second is their count over the time, "late" the share more than 25 ms apart. The line ends with its numbers as DATA {…}. Each computer's figures here are one run of it.
The computers. The Ubuntu laptop: an Intel i7, Firefox 136 on Ubuntu, 1440×810 at 2×, 4 cores. The iPad: Safari (reports itself as "Safari 605", "MacIntel"), 810×1080 at 2×, 4 cores. Matthew's laptop: Firefox 157 on Linux, 1203×802 at 1.875×, 20 cores. The kids' lines were pasted into the pad on 2026-10-16 (0.0.84 and 0.0.86 in the afternoon, 0.0.92 in the evening); Matthew's into the chat.
On Matthew's laptop, the headless runs: trips_perf.mjs (headless Chrome 155, with a CPU profile) and tripsff.py (headless Firefox 157, the page's code run from an added <script>), each trip from a fresh page; choppy172.mjs for the marking; stillpic164.mjs with stillpic_diff.py for the pictures against the scene. Every browser was pinned to 4 of the laptop's 20 threads, as the laptop crashes under load (the gate reads the same pinned: 10 of 10 at 59.3 to 60 on 0.0.86 both ways). Copies are in 002/drivers/. The frame-rate gate (fpsgate.mjs, ^du_report(1)) passed on every release here (10 cases on 0.0.86, 12 from 0.0.87, with a slow computer's duck pond added).
The data is here twice: embedded in this page as JSON (<script type="application/json" id="report-data"> at its end: every line's numbers, the headless timings and checks, the versions and commits) and as files in 002/data/: lines.json (the pad's lines, each with its computer), matthews-laptop.json, headless-and-checks.json, pad-2026-10-16.txt (the pad as it was), and the gate's logs.
Builds: 0.0.84 151085a, 0.0.86 c49d6f2, 0.0.87 431d897, 0.0.90 9958ca2, 0.0.91 51f13e1, 0.0.92 119c5c6, 0.0.93 eebaa60.