Public: anyone can read this; the crew can change it.
forked from trevato/cs
What a room costs, measured before anything is built on it: the world stepped headless in this process, at a ceiling a test holds #346
Check · Review · Land · Live done — Landed and live in production.
`scripts/room.ts` is the bench this issue asked for: it builds a real `createRoom` — ten bodies on de_forge, the shipped policy thinking, the freeze set aside — steps it with `stepRoom` at 64 Hz, and prints milliseconds of CPU per simulated world-second with bots thinking and with every seat driven by input frames instead, the policy's share of the difference, the snapshot in three encodings over…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
scripts/room.tsis the bench this issue asked for: it builds a realcreateRoom— ten bodies on de_forge, the shipped policy thinking, the freeze set aside — steps it withstepRoomat 64 Hz, and prints milliseconds of CPU per simulated world-second with bots thinking and with every seat driven by input frames instead, the policy's share of the difference, the snapshot in three encodings over 128 real beats of that round, the bytes a member a second at 8/16/32 Hz for each, what each costs this process to encode, and how many rooms one core holds at a stated margin. Nothing about the game changed: no route, no socket, no dependency, and no module the server imports gained a line of code.Measured on the forge's box (Intel Xeon Gold 6230, 80 shared cores at load ~20, bun 1.3.14), eight-second window, median of seven batches, four runs: a room-second of ten bots thinking is 5.4–8.1 ms, 10–24 ms in the round's dearest single second; the same room with all ten seats held by members and nobody thinking is 2.5–3.0 ms, of which 0.35–0.54 ms is the input frames off the wire — so the ten policies are 60–70% of a thinking room. A snapshot is 514 B packed (764 B widest), 3.8 kB as JSON, 684 B as gzipped JSON, which is 8.2 / 61.4 / 10.9 kB a second a member at 16 Hz; encoding one costs 0.006, 0.019 and 0.066 ms, so gzip buys 170 bytes a beat over the packed frame for ten times its CPU. The answer: a whole room — the step plus ten packed snapshots at 16 Hz — costs 6.4–9.0 ms of CPU a second, so one core holds 55–78 rooms, or 19–45 if every room hits its dearest second at once;
ROOM_CAPat 20 is a sixth of a core, a choice about a box that also serves pages rather than a limit the simulation imposed. Excluded, deliberately: the socket — no connection is opened, so the kernel's share of those bytes is in no number here.The finding is held as a ceiling in
src/budget.test.ts, in that file's own idiom: a room-second must cost under 40 ms in this process (the test's own second — the first of a live round — reads 4.6 ms), with a proof beside it that a room-second sixteen times dearer trips it.measurethere gained one optional argument so the printed line says whether the ceiling is a slice of a frame or of the second a room has.src/rooms/hub.tsandROOM_CAP's docstring now cite the measured figures instead of the earlier estimate of "about 5 ms", and the README carries the table, the machine, and both new commands. What I chose not to do: pick an encoding — that is #304's — and fix the per-tick seatMapstepRoomrebuilds, which the bench shows but which is a change to the game.Worth a look: the table itself (
bun run scripts/room.ts), the "dearest second" column, which is the number a deployment should be sized by and is the noisiest reading on a shared box, andscripts/room.test.ts, which asserts the JSON candidate carries the same round the packed one does so the comparison is not flattering the winner.🤖 Generated with Claude Code
Closes #302