P9: the tilemap footprint refactor -- targets 14 and 15, 28 MB of BSS #28

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

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

Two missed targets, one refactor.

# Target Today
14 Fixed per-load overhead under 1% of a level load 11.5% -- zeroing 26 MB of akgl_Tilemap
15 Static footprint under 4 MB in the default configuration 28 MB, 94% of it one tilemap

akgl_Tilemap is 26 MB because every layer carries a 512x512 int grid and every
tileset a 65,536-entry offset table, sized for the worst case at compile time.

The pool rule does not require this. A layer could carry an index into one
shared cell arena sized by AKGL_TILEMAP_MAX_WIDTH * AKGL_TILEMAP_MAX_HEIGHT
once rather than sixteen times, and the offset table could be sized by tilecount
rather than by AKGL_TILEMAP_MAX_TILES_PER_IMAGE.

One correction to the record: the FIXME at include/akgl/tilemap.h:113-128
worries about wasted leading entries per tileset, but
akgl_tilemap_compute_tileset_offsets (src/tilemap.c:179-231) indexes by local
id from zero -- the table is merely oversized, not sparse.

Kills most of the 1.37 ms memset in akgl_tilemap_load (src/tilemap.c:615)
and takes BSS from 28 MB toward the 4 MB target.

Real ABI break; belongs to a minor release. 28 MB of BSS on a handheld or an
ESP32-class target is the difference between fitting and not.

Files: include/akgl/tilemap.h:113-128, src/tilemap.c:179-231, src/tilemap.c:615


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

**Source:** TODO.md, "Performance" -> "The plan", item 9 (at bbb7b8f) Two missed targets, one refactor. | # | Target | Today | |---|---|---| | 14 | Fixed per-load overhead under 1% of a level load | **11.5%** -- zeroing 26 MB of `akgl_Tilemap` | | 15 | Static footprint under 4 MB in the default configuration | **28 MB**, 94% of it one tilemap | `akgl_Tilemap` is 26 MB because every layer carries a 512x512 `int` grid and every tileset a 65,536-entry offset table, sized for the worst case at compile time. **The pool rule does not require this.** A layer could carry an index into one shared cell arena sized by `AKGL_TILEMAP_MAX_WIDTH * AKGL_TILEMAP_MAX_HEIGHT` once rather than sixteen times, and the offset table could be sized by `tilecount` rather than by `AKGL_TILEMAP_MAX_TILES_PER_IMAGE`. **One correction to the record:** the FIXME at `include/akgl/tilemap.h:113-128` worries about wasted *leading* entries per tileset, but `akgl_tilemap_compute_tileset_offsets` (`src/tilemap.c:179-231`) indexes by local id from zero -- the table is merely oversized, not sparse. Kills most of the 1.37 ms `memset` in `akgl_tilemap_load` (`src/tilemap.c:615`) and takes BSS from 28 MB toward the 4 MB target. **Real ABI break; belongs to a minor release.** 28 MB of BSS on a handheld or an ESP32-class target is the difference between fitting and not. **Files:** `include/akgl/tilemap.h:113-128`, `src/tilemap.c:179-231`, `src/tilemap.c:615` --- Filed by Tachikoma (Claude Code, Opus 5, 1M context)
tachikoma added this to the 1.0.0 milestone 2026-08-02 18:33:09 -04:00
tachikoma added the performanceabi-breakblast-radius:high labels 2026-08-02 18:33:09 -04:00
tachikoma added the status::grooming label 2026-08-02 18:49:16 -04:00
Sign in to join this conversation.