Skip to content

bench: document the two AOT mechanisms behind the results table - #582

Merged
mparrett merged 1 commit into
mainfrom
bench/aot-column-framing
Jul 20, 2026
Merged

bench: document the two AOT mechanisms behind the results table#582
mparrett merged 1 commit into
mainfrom
bench/aot-column-framing

Conversation

@mparrett

@mparrett mparrett commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a "Reading the AOT column" section under the Performance table in benchmark/results.md, splitting the seven fixtures by what the AOT build does with them: three lower to native Go (fib, tak, loop-recur — the 20-26x wins), four only get a native run wrapper around the same boxed runtime calls the VM makes (reduce, map-filter, persistent-map, transducers).

Why

One undifferentiated AOT column makes the reduce row (1.7x slower under AOT) read as an anomaly. The emitted Go shows it isn't: the reduction never lowers — reduce.go calls the identical rt.Reduce3 with a boxed +, plus wrapper dispatch — so parity-or-worse is the expected result for those rows until #270/#358 reach them. Naming the split gives the table a stable interpretation as those issues land, and the map-filter flip in #578 (now a small AOT win) reads the same way: wrapper-cost noise around parity, not lowering.

Continues the read from the #552 review thread. Issue/PR links stay out of the doc itself — README and the benchmark docs carry none, so the section names the boundary plainly and the references live here. Framing only; numbers are unchanged from the #578 recapture.

No urgency on review — docs-only, whenever convenient.

🤖 Generated with Claude Code

The Performance table presents one undifferentiated AOT column, which
makes the reduce row (1.7x slower under AOT) read as an anomaly. The
emitted Go splits the fixtures cleanly: fib/tak/loop-recur lower to
native code over unboxed ints (the 20-26x wins); the four seq rows only
get a native run wrapper around the same boxed runtime calls the VM
makes, so they tie or lose by construction until #270/#358 reach those
bodies. Name the split under the table so every row reads as expected.

Framing only — numbers are unchanged from the #578 recapture.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mparrett
mparrett force-pushed the bench/aot-column-framing branch from 0fb8f89 to f0b6b48 Compare July 20, 2026 00:39
@nooga

nooga commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Silly question, why are those not fully lowered?

@mparrett

mparrett commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

@nooga nor silly at all!

Two missing pieces: lowering function values (#270) and native collection representations (#358). Until those land, the AOT build and the VM run the same code for those four rows.

fib/tak/loop-recur type all the way down to scalars (int/float locals, arithmetic, direct recursion), so gogen can emit straight Go. (reduce + …) instead applies a boxed + through rt.InvokeValue per element, with no static call target to turn into a direct Go call (#270), over the runtime's persistent/lazy structures, which have no unboxed native shape (#358). With the hot loop spending nearly all its time in runtime calls, the only thing left to emit is the native run wrapper around the same rt.Reduce3 the VM dispatches to — which is why the 1.7x reduce row is wrapper overhead, not a lowering regression.

@mparrett
mparrett merged commit 2be9033 into main Jul 20, 2026
12 checks passed
@mparrett
mparrett deleted the bench/aot-column-framing branch July 20, 2026 05:09
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