P2: text texture ring cache -- targets 8 and 9, one cache #22

Open
opened 2026-08-02 18:33:02 -04:00 by tachikoma · 0 comments
Collaborator

Source: TODO.md, "Performance" -> "The plan", item 2 (at bbb7b8f)

Two missed targets, one cache.

# Target Today
8 Re-drawing an unchanged line of text under 1 us 12.6 us, every frame, no cache
9 Zero texture creation or destruction per frame in steady state one create + one destroy per line of text per frame

This is the clearest optimisation in the library and it is maybe forty lines.

A static four-to-eight entry ring in src/text.c keyed on (TTF_Font *, text
bytes, SDL_Color, wraplength). x/y stay out of the key -- position only
affects dest.

Invalidate in akgl_text_unloadfont (src/text.c:40-55) and
akgl_text_unloadallfonts (:76-87).
A cached texture keyed on a closed font
whose address was reused is a stale hit, so unload must sweep the ring.

Verification is a counting test, not a stopwatch. Target 9 is zero texture
create/destroy per steady-state frame, so count them through a stub. Plus a new
perf row ("rendertextat, cached") with the raw-SDL control row the perf rules
require. Budget to move: tests/perf_render.c:391.

The UI subsystem is this cache's second consumer, and the bigger one.
akgl_ui_execute_commands (src/ui.c) draws every TEXT render command through
akgl_text_rendertextat, one wrapped line per command per frame -- a menu of five
rows re-rasterizes five lines at 60 Hz whether or not any of them changed, where
the original HUD case was one line changing once a second. Abstract-on-the-second-
consumer says this item's time has come; the key already fits, since clay hands
the executor stable text bytes between frames.

Files: src/text.c:40-55,76-87, src/ui.c, tests/perf_render.c:391


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

**Source:** TODO.md, "Performance" -> "The plan", item 2 (at bbb7b8f) Two missed targets, one cache. | # | Target | Today | |---|---|---| | 8 | Re-drawing an unchanged line of text under 1 us | **12.6 us**, every frame, no cache | | 9 | Zero texture creation or destruction per frame in steady state | one create + one destroy per line of text per frame | This is the clearest optimisation in the library and it is maybe forty lines. A static four-to-eight entry ring in `src/text.c` keyed on (`TTF_Font *`, text bytes, `SDL_Color`, wraplength). `x`/`y` stay out of the key -- position only affects `dest`. **Invalidate in `akgl_text_unloadfont` (`src/text.c:40-55`) and `akgl_text_unloadallfonts` (`:76-87`).** A cached texture keyed on a closed font whose address was reused is a stale hit, so unload must sweep the ring. **Verification is a counting test, not a stopwatch.** Target 9 is *zero* texture create/destroy per steady-state frame, so count them through a stub. Plus a new perf row ("rendertextat, cached") with the raw-SDL control row the perf rules require. Budget to move: `tests/perf_render.c:391`. **The UI subsystem is this cache's second consumer, and the bigger one.** `akgl_ui_execute_commands` (`src/ui.c`) draws every TEXT render command through `akgl_text_rendertextat`, one wrapped line per command per frame -- a menu of five rows re-rasterizes five lines at 60 Hz whether or not any of them changed, where the original HUD case was one line changing once a second. Abstract-on-the-second- consumer says this item's time has come; the key already fits, since clay hands the executor stable text bytes between frames. **Files:** `src/text.c:40-55,76-87`, `src/ui.c`, `tests/perf_render.c:391` --- Filed by Tachikoma (Claude Code, Opus 5, 1M context)
tachikoma added this to the 0.9.x milestone 2026-08-02 18:33:02 -04:00
tachikoma added the performanceblast-radius:high labels 2026-08-02 18:33:02 -04:00
tachikoma added the status::grooming label 2026-08-02 18:49:15 -04:00
Sign in to join this conversation.