P6: draw_world rescans all 64 actor slots once per layer -- 1024 refcount checks a frame #26

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

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

akgl_render_2d_draw_world (src/renderer.c:150-167) walks all
AKGL_TILEMAP_MAX_LAYERS and, for each, rescans all AKGL_MAX_HEAP_ACTOR slots
-- 1024 refcount checks a frame for a one-layer map.

Half of this entry is already done and the issue is the other half. The
tilemap blit is guarded by if ( i < akgl_gamemap->numlayers ), so a one-layer
map draws one layer. The actor loop is not bounded by anything: it runs 16 times
regardless, and each pass reads every slot in the pool to find the ones on that
layer.

Fix: bound the outer walk by akgl_gamemap->numlayers, and build the
per-layer actor lists in one pool pass into static index arrays rather than
rescanning per layer.

Invisible at 60 fps under the software renderer; measurable on a 2 ms GPU frame.
Counting test, same shape as the tileset-scan issue.

Note the interaction: bounding the outer walk by numlayers makes the
"actor on a layer past the last map layer is never drawn" defect sharper rather
than fixing it -- see the separate issue on akgl_Actor::layer being unbounded.

Files: src/renderer.c:150-167


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

**Source:** TODO.md, "Performance" -> "The plan", item 6 (at bbb7b8f) `akgl_render_2d_draw_world` (`src/renderer.c:150-167`) walks all `AKGL_TILEMAP_MAX_LAYERS` and, for each, rescans all `AKGL_MAX_HEAP_ACTOR` slots -- **1024 refcount checks a frame for a one-layer map**. **Half of this entry is already done and the issue is the other half.** The tilemap blit is guarded by `if ( i < akgl_gamemap->numlayers )`, so a one-layer map draws one layer. The actor loop is not bounded by anything: it runs 16 times regardless, and each pass reads every slot in the pool to find the ones on that layer. **Fix:** bound the outer walk by `akgl_gamemap->numlayers`, and build the per-layer actor lists in one pool pass into static index arrays rather than rescanning per layer. Invisible at 60 fps under the software renderer; measurable on a 2 ms GPU frame. Counting test, same shape as the tileset-scan issue. **Note the interaction:** bounding the outer walk by `numlayers` makes the "actor on a layer past the last map layer is never drawn" defect sharper rather than fixing it -- see the separate issue on `akgl_Actor::layer` being unbounded. **Files:** `src/renderer.c:150-167` --- Filed by Tachikoma (Claude Code, Opus 5, 1M context)
tachikoma added this to the 0.9.x milestone 2026-08-02 18:33:07 -04:00
tachikoma added the performanceblast-radius:medium labels 2026-08-02 18:33:07 -04:00
tachikoma added the status::grooming label 2026-08-02 18:49:16 -04:00
Sign in to join this conversation.