Test the collision scan, and measure what it costs
`spr_collisions()` had no test. `tests/sprite_verbs.c` drives the collision path end to end but through a mock backend, so the real overlap arithmetic in `src/sprite_akgl.c` could have changed what `BUMP(1)` reports for every program in existence and the suite would still have printed 110/110. That gap is closed here, before anything touches the arithmetic, so that there is a *before* to compare an *after* against. Six cases against the real akgl backend: nothing defined, two sprites overlapping, edge-to-edge, a hidden sprite, and the x-expand bit doubling the box that collides rather than only the one that draws. Edge-to-edge earns its place -- the test is a strict `<`, a tile-aligned program puts sprites there constantly, and a replacement answering "touching" instead of "overlapping" would change every one of them silently. **The seventh is the cross-shaped overlap**, and it is the one to watch. A tall thin sprite crossing a short wide one overlaps without either rectangle holding a corner of the other; `akgl_collide_rectangles()` is documented as answering "no" there, which is why `src/sprite_akgl.c` does the four comparisons itself rather than calling it. Two further assertions stop that test passing by accident: each sprite is moved clear along the axis it is supposed to be short on, so a sprite that came out the wrong size fails rather than quietly reporting an ordinary overlap. `tests/collision_perf.c` answers the question nobody had measured. The service runs at the top of every interpreter *step* and the frontend takes 256 steps per rendered frame, so a busy program scans up to 256 times a frame over sprites that have not moved. At RelWithDebInfo, scale 10, best of 5: the scan is 96.3 ns at eight overlapping sprites and 19.4 ns at none, against a rendered frame of 1.17 ms. **256 scans is 24.7 us, or 2.1% of a frame, in the pathological case, and 0.42% for a program with no sprites.** So the per-step cadence stays. It is what makes a collision report describe where the sprites have just been moved to rather than where they were, and 2% of a frame in a case no real program reaches is not worth changing when a handler fires for every program that already works. The numbers and that conclusion are in `MAINTENANCE.md` so it does not get re-argued. The benchmark borrows libakgl's `benchutil.h` by include path rather than copying it, the way the fixture font is already borrowed, and is labelled `perf` so `ctest -LE perf` can leave it out. It runs at scale 1 in the ordinary suite -- 1.2 seconds -- because a benchmark nothing ever builds is a benchmark that rots. Both suites green: 111 with akgl, 110 without. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwxGB6TdoVvZ11KQQME9cL
This commit is contained in:
@@ -354,6 +354,27 @@ if(AKBASIC_WITH_AKGL)
|
||||
TIMEOUT 60
|
||||
ENVIRONMENT "SDL_VIDEODRIVER=dummy;SDL_AUDIODRIVER=dummy")
|
||||
|
||||
# What the collision scan costs against what a frame costs. Labelled `perf` so
|
||||
# `ctest -LE perf` leaves it out of the ordinary run: it is the only test here
|
||||
# that deliberately spends wall-clock time, and the numbers are meaningless in
|
||||
# the Debug trees anyway -- see the file's own header.
|
||||
add_executable(akbasic_test_collision_perf tests/collision_perf.c)
|
||||
target_compile_options(akbasic_test_collision_perf PRIVATE -Wall -Wextra)
|
||||
target_link_libraries(akbasic_test_collision_perf PRIVATE akbasic_akgl)
|
||||
# libakgl's benchmark harness, borrowed by include path rather than copied, for
|
||||
# the same reason the fixture font is: a second copy is a fork. SYSTEM because
|
||||
# benchutil.h is a header of statics and -Wunused-function would fire on every
|
||||
# helper this suite happens not to call.
|
||||
target_include_directories(akbasic_test_collision_perf SYSTEM PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/libakgl/tests")
|
||||
target_compile_definitions(akbasic_test_collision_perf PRIVATE
|
||||
AKBASIC_TEST_FONT="${CMAKE_CURRENT_SOURCE_DIR}/deps/libakgl/tests/assets/akgl_test_mono.ttf")
|
||||
_add_test(NAME collision_perf COMMAND akbasic_test_collision_perf)
|
||||
_set_tests_properties(collision_perf PROPERTIES
|
||||
LABELS perf
|
||||
TIMEOUT 300
|
||||
ENVIRONMENT "SDL_VIDEODRIVER=dummy;SDL_RENDER_DRIVER=software")
|
||||
|
||||
# The frontend suite. Separate from the one above because it tests the *host*
|
||||
# rather than the adaptors -- it is the only test that links akbasic_frontend,
|
||||
# and the only one that opens a window and pumps events. It uses the
|
||||
|
||||
Reference in New Issue
Block a user