bench: apply mcode arena hardening across all bench scripts (3qu)
Added jit.opt.start('sizemcode=64', 'maxmcode=4096') to all 9 bench
scripts. Same fix 3o2 landed in bench/jit_trace.lua, propagated to the
rest. Without it, the macOS arm64 mcode allocator intermittently fails
to find an executable page in the signed-32-bit offset window and the
bench reports interpreter-only throughput with no diagnostic — visible
as silent regressions. The risk is higher in scripts with larger codegen
footprints than the trace gate.
Files touched: bench.lua, lazy_bench.lua, profile.lua, shapes_bench.lua,
starwing_bench.lua, wire_bench.lua, alloc_probe.lua, map_bench.lua,
packed_bench.lua. All 7 non-interactive scripts run rc=0; profile and
starwing loadfile-check clean.
Also refreshed bench/baseline.json per the issue's step 2. Surprise win:
full-mode decode allocations dropped 0.5-50% as a side-effect of auj/ozn
that was only visible after the snapshot. Most notable: proto2_basic
BenchPayload mid decode 2.313 -> 1.156 KB/op (-50%), Person 1KB decode
0.977 -> 0.953 KB/op. Runtime-mode unchanged — confirms the alloc
reduction is full-mode codegen specific.
Steps 3-4 (refresh COMPARISON.md throughput tables, verify the variance
band shrinks below the documented 5-10% drift) are deferred to a
work.lab.local run — laptop variance is 50%+ on identical state, can't
trust throughput A/Bs locally.
bench: lazy decode/encode scenarios + jit-trace coverage
Adds bench/lazy_bench.lua comparing eager decode/encode against
decode_lazy:encode across three workloads (passthrough, sparse-read,
mutate-then-reencode) at 1KB/10KB/100KB on emails-heavy Person.
Output is stderr-only (varies with CPU load; not committed to
baseline.json).
Findings (LuaJIT 2.1.0-beta3, both modes):
- Passthrough re-encode: lazy 1.0–1.5× faster. Untouched views skip
field-walk entirely and return their original bytes verbatim.
- Sparse :get x2: lazy 0.60–0.77× of eager. Per-segment Lua tables
allocated during the index pass cancel the decode-skip savings on
this flat shape (no large subtrees to skip_field over).
- Mutate-then-reencode: lazy 0.81–1.07× of eager — roughly
break-even. Both paths traverse the full byte range; lazy
splices, eager re-emits per field.
Lazy is a byte-passthrough optimization, not a universal speedup. Use
it when you decode, touch few fields, and re-encode — the proxy /
router shape.
Also extends bench/jit_trace.lua with three lazy hot-path checks:
index pass, sparse :get x2, and untouched :encode. All compile with
no fatal aborts (19/19 trace-stability checks pass; one harmless
side-trace bridge per scenario at lazy.lua's index loop, same pattern
as the existing decode_varint bridge).