Skip to content

Compile out diagnostic prints unless AMY_PRINT is defined; keep for CPython - #1035

Closed
bwhitman wants to merge 2 commits into
mainfrom
amy-print
Closed

Compile out diagnostic prints unless AMY_PRINT is defined; keep for CPython#1035
bwhitman wants to merge 2 commits into
mainfrom
amy-print

Conversation

@bwhitman

@bwhitman bwhitman commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

AMY's warnings — "note off does not match note on", parse errors, the debug dumps — were unconditional fprintf(stderr, ...)/printf(...) calls. On microcontrollers those are blocking serial writes in or near the render path, and their format strings cost flash.

The change

All 245 diagnostic print sites in the core sources now go through one macro, amy_printf() in amy.h:

  • AMY_PRINT definedfprintf(stderr, ...), exactly as before.
  • Not defined (the default) → the call sits behind if (0), so the arguments stay type- and format-checked and count as used (no -Wunused-* warnings on any of the strict targets), while every optimizing build strips both the call and its strings. Verified with strings on the desktop binary: with AMY_PRINT unset, "does not match note on" et al. are gone from the executable — so this saves flash as well as runtime.

Who prints, by default

  • CPython (setup.py): -DAMY_PRINT — behavior unchanged, warnings still appear.
  • Everything else (Arduino, web, Godot, the desktop Makefile targets): silent. Opt back in with -DAMY_PRINT in your build flags.

Deliberately untouched

  • amy_oom() still counts OOMs unconditionally (amy_get_oom_count() keeps working headlessly); only its one-time report is gated.
  • AMY_PROFILE_PRINT only exists under AMY_DEBUG, an explicit developer build, so it keeps its raw fprintf.
  • amy-example / amy-message / amy-piano / pyamy.c are desktop-only user-facing programs and keep their own prints, as do the ctests in tests/.
  • Vendored miniaudio.h untouched.

Testing

  • make test: 122 WAV tests pass bit-exact (CPython build, prints on).
  • make ctest: all three suites pass (built without AMY_PRINT, so they also prove the behavior-not-output contract of the sequencer tests).
  • make amy-example: builds warning-free with the macro compiled out.

🤖 Generated with Claude Code

…Python

AMY's warnings ("note off does not match note on", parse errors, debug
dumps) were unconditional fprintf(stderr)/printf calls. On
microcontrollers those are blocking serial writes in or near the render
path, and their format strings cost flash.

All 245 diagnostic print sites in the core sources now go through an
amy_printf() macro (amy.h). With AMY_PRINT defined it is
fprintf(stderr, ...); without it the call sits behind `if (0)` so the
arguments stay type- and format-checked and count as used (no -Wunused
warnings), while every optimizing build strips the call and its strings
-- verified by `strings` on the desktop binary: the warning text is
gone when AMY_PRINT is unset.

Only the CPython build (setup.py) defines AMY_PRINT for now; Arduino,
web, Godot, and the desktop Makefile targets are silent by default and
can opt back in with -DAMY_PRINT. amy_oom() still counts OOMs either
way; only its report is gated. The AMY_PROFILE_PRINT macro is left
alone: it only exists under AMY_DEBUG, which is an explicit developer
build. amy-example/amy-message/amy-piano/pyamy keep their own prints
(desktop-only user-facing binaries).

make test: 122 WAV tests pass bit-exact. make ctest passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bwhitman
bwhitman requested a review from dpwe August 2, 2026 15:17
The load-sweep bench's measure.py parses these lines over serial, and
gating them behind AMY_PRINT made the HWCI bench capture nothing. This
output is instrumentation, not diagnostics, and it's already opt-in via
ARDUINO_SPEEDTEST -- it must print whether or not AMY_PRINT is set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🎛️ AMY HW CI (AMYboard bench)

Flashed this PR's AMY (LoadTestChord: 6-voice Juno patch=1, one held note every 2 s) onto the physical AMYboard and measured the smoothed render load as the chord grows — back-to-back with the same sketch built at the PR's merge base, so Δ is this PR's own cost.

PASS — the bench ran the test to completion.

notes held main @ 3020e20 this PR Δ
1 1041 1032 -9
2 1198 1182 -16
3 1793 1763 -30
4 1952 1935 -17
5 2604 2560 -44
6 2760 2755 -5

Full chord settled render μs: 2756 (was 2762, Δ -0.2%) (peak 2759, 39 samples)

⬇️ Artifacts: serial log · load trace · report

Self-hosted bench (amyboardci). FAIL means only that the test could not run — the load values are informational, with no threshold and no audio compare. See tools/arduino_loadsweep/.

@dpwe

dpwe commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

The argument was that these printfs indicate real issues pointing to unexpected behavior - I like seeing them, even over serial from an AMYboard. The timing shows essentially no benefit (I think?). Saving flash probably isn't a huge deal since we usually have a lot.

The changes look fine, it's clean, but I'm wondering what drew your attention to it? "Note off does not match note on" indicates something that might deserve an explanation.

@bwhitman

bwhitman commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

The timing on AMY hwci does not exercise the problem (and never meant to.) I'll write up what I'm actually seeing.

@bwhitman

bwhitman commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator Author

The slowdown only happens when the fprintfs are spamming faster than UART 115200 , so this is not a day to day concern for anyone. Since you don't want it anyway i'll close it

@bwhitman bwhitman closed this Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants