Files
libakgl/CMakeLists.txt
Andrew Kesterson bcd49fc5b1 Measure the library: perf suites, a recorded baseline, and targets
tests/perf.c and tests/perf_render.c drive the hot paths hard enough to
time them -- pool acquire and release at both ends of the scan, the
registry, the state-to-sprite lookup, the per-actor update and render, the
physics sweep, an all-pairs collision sweep, the JSON accessors, path
resolution, the drawing primitives, text, asset loading, a screenful of
tiles, and a whole frame through akgl_game_update. They are registered like
any other suite but carry the `perf` label, so `ctest -L perf` runs only
them and `-LE perf` leaves them out. Every measurement is held to a budget
at roughly ten times the recorded baseline, enforced only in an optimized
build at full scale.

Three things had to be got right before the numbers meant anything, and
each was wrong first:

- No error checking inside the clock. PASS and CATCH call
  akerr_valid_error_address, which walks AKERR_ARRAY_ERROR -- more work than
  several of the calls being measured.
- Flush the renderer before stopping it. SDL batches, so the first version
  measured queueing, reported a tilemap frame 250 times faster than it is,
  and paid the real cost at teardown inside SDL_DestroyTexture.
- A drawing benchmark needs a raw-SDL control doing the same pixel work
  with the same access pattern. With one, akgl_tilemap_draw turns out to
  cost 0.2% of the frame it appeared to own: 16.26 ms against a control's
  16.23 ms for the same 1200 blits. The rasterizer is the frame.

PERFORMANCE.md records the baseline, the frame budget it adds up to, and
what the numbers say -- including that the string pool's acquire is 64x
slower full than empty because it is a megabyte of PATH_MAX buffers, that a
handled missing-sprite condition costs nine times the update it replaces,
that text rasterizes and throws away a texture on every call, and that 28 MB
of the library's BSS is one akgl_Tilemap.

TODO.md gains a Performance section: five defects the stress tests found
that the unit suites do not reach (a tilemap load leaking five pooled
strings, two JSON accessors that turn pool exhaustion into a segfault
rather than AKGL_ERR_HEAP, akgl_game_update crashing without
akgl_game_init, and its actor update sweep running once per tilemap layer),
and eighteen targets with today's number and whether it is met.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 14:24:05 -04:00

16 KiB