From 48b1060fa66f5f69dac6d652b4013cdaf1d2bd1f Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 25 Aug 2026 19:29:07 -0300 Subject: Never build the P4 object Debug; the measured mode becomes the default `-Doptimize` defaults to Debug, so the naive `zig build -Dplatform=p4` produced an object that CANNOT RUN. Debug wraps every tier in `allocators.zig` in a `DebugAllocator`, whose metadata is page-granular, and one 4 KiB page per size class does not fit in the 384 KiB the board hands the editor: the image links, flashes, and then dies in `Pardes.init`. Nothing said so, because every build in this session happened to pass `-Doptimize=` explicitly. The p4 target now falls back to ReleaseFast, and that mode was measured rather than preferred. On the die, against ReleaseSmall over 5 document lengths x 7 trials: configuration fixed per char at 160 chars ReleaseSmall 16.99 ms 54.3 us 25.56 ms ReleaseFast 14.85 ms 34.7 us 20.30 ms 0.79x 13% off the fixed per-keystroke cost, 36% off the per-character cost, for 35% more flash on a partition that is 39% used. An explicit `-Doptimize=` still wins, so ReleaseSmall stays one flag away when flash matters more than latency - which is why this is a fallback and not a hard override. Following the file's own convention: the web target has pinned ReleaseSmall unconditionally for the same kind of reason (size is its budget) since before this. --- build.zig | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/build.zig b/build.zig index 01fed2b6..c9ae800f 100644 --- a/build.zig +++ b/build.zig @@ -128,8 +128,23 @@ pub fn build(b: *std.Build) void { const enable_jpx = b.option(bool, "jpx", "JPEG 2000 in PDFs, for scanned documents (default on; -Djpx=false drops openjpeg)") orelse true; const is_web_target = target.result.cpu.arch == .wasm32 and target.result.os.tag == .freestanding; const is_p4_target = target.result.cpu.arch == .riscv32 and target.result.os.tag == .freestanding; - // wasm: size is the budget - const optimize = if (is_web) .ReleaseSmall else requested_optimize; + // wasm: size is the budget. + // + // p4: Debug is not a supported mode, and `-Doptimize` defaulting to it made the naive + // `zig build -Dplatform=p4` produce an object that cannot run. Debug wraps every tier in + // `allocators.zig` in a `DebugAllocator`, whose metadata is page-granular; the board hands the + // editor a 384 KiB heap and one 4 KiB page per size class does not fit in it, so the image + // links and then dies in `Pardes.init`. ReleaseFast rather than ReleaseSmall because it was + // measured on the die and not chosen: against ReleaseSmall it is 13% off the fixed + // per-keystroke cost and 36% off the per-character cost, for 35% more flash on a partition + // that is 39% used. See experiments/report.typ. An explicit `-Doptimize=` still wins, so + // ReleaseSmall remains one flag away when flash matters more than latency. + const optimize = if (is_web) + .ReleaseSmall + else if (is_p4_target and requested_optimize == .Debug) + .ReleaseFast + else + requested_optimize; // The vendored C is never what we are debugging, and at -O0 it dominates // the app: 90% of a Debug startup is tree-sitter's query analyser // (perf: ts_query__perform_analysis + ts_lookahead_iterator__next), and -- cgit v1.3