The only vsync is spinning on TI#, and the spin starves the PLAY queue dry #22

Open
opened 2026-08-02 19:04:27 -04:00 by tachikoma · 0 comments
Collaborator

Source: TODO.md §4 (at 9151438)

Chapter 13 documents the polling; the demo's first cut had the loop -- read TI#, branch to
yourself until it moves -- and it did not just waste CPU, it starved the PLAY queue dry.

The chain is measurable. The host calls settime() once per runtime_run() batch, and
akbasic_play_service() can therefore release at most one note per batch (after a release,
nextms sits ahead of the frozen clock). A batch of 256 held SLEEP steps is nearly free, but a
batch of 256 executed spin statements is slow enough to drop the release rate below a
sixteenth-note tune's fifteen notes a second -- and the queue never reclaims slots until it
drains completely
, so the backlog compounded across scenes and overflowed the 128-note queue with
PLAY queue is full.

Reproduced both ways in isolation: the same tune requeued eight times over a SLEEP loop
survives; over a TI# spin it dies on the third batch. The demo's VSYNC label now sleeps a frame
instead.

A verb that parks the program until the next batch boundary (SLEEP 0 is an available
spelling) is the same hold-without-blocking shape SLEEP and GETKEY already have in
src/runtime_console.c, and it would make the honest spelling also the safe one.

Files: src/runtime_console.c, src/play.c, docs/13-differences.md


Filed by Tachikoma (Claude Code, Opus 5, 1M context)

**Source:** TODO.md §4 (at 9151438) Chapter 13 documents the polling; the demo's first cut had the loop -- read `TI#`, branch to yourself until it moves -- and **it did not just waste CPU, it starved the `PLAY` queue dry.** **The chain is measurable.** The host calls `settime()` once per `runtime_run()` batch, and `akbasic_play_service()` can therefore release **at most one note per batch** (after a release, `nextms` sits ahead of the frozen clock). A batch of 256 *held* `SLEEP` steps is nearly free, but a batch of 256 *executed* spin statements is slow enough to drop the release rate below a sixteenth-note tune's fifteen notes a second -- **and the queue never reclaims slots until it drains completely**, so the backlog compounded across scenes and overflowed the 128-note queue with `PLAY queue is full`. **Reproduced both ways in isolation:** the same tune requeued eight times over a `SLEEP` loop survives; over a `TI#` spin it dies on the third batch. The demo's `VSYNC` label now sleeps a frame instead. **A verb that parks the program until the next batch boundary** (`SLEEP 0` is an available spelling) is the same hold-without-blocking shape `SLEEP` and `GETKEY` already have in `src/runtime_console.c`, **and it would make the honest spelling also the safe one.** **Files:** `src/runtime_console.c`, `src/play.c`, `docs/13-differences.md` --- Filed by Tachikoma (Claude Code, Opus 5, 1M context)
tachikoma added this to the 0.2.0 milestone 2026-08-02 19:04:27 -04:00
tachikoma added the performanceapi-gapblast-radius:highstatus::grooming labels 2026-08-02 19:04:27 -04:00
Sign in to join this conversation.