Skip to content

landing: the measured conformance and AOT figures, and an honest Go API card - #13

Merged
tannevaled merged 1 commit into
mainfrom
wave34-docs-go-embedded-ruby.github.io
Sep 26, 2026
Merged

tannevaled merged 1 commit into
mainfrom
wave34-docs-go-embedded-ruby.github.io

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Re-measured on 3e8e3cc (darwin/arm64) against MRI 4.0.5 on the same host.

The performance headline did not hold

The site claimed "rbgo+AOT beats MRI+YJIT 18–24× on loop/fib" in four places. It fails on two independent readings.

First, it does not follow from the numbers it cites. BENCHMARKS.md's own table gives, for loop, AOT 10 ms against YJIT 360 ms (36×), and for fib, AOT 20 ms against YJIT 100 ms (5×). Neither is 18–24×, and no average of them is.

Second, re-running this project's own benchmarks here (bench/loop.rb, bench/fib.rb, hyperfine, whole-process wall time):

rbgo+AOT MRI+YJIT ratio
loop (sum_to(20_000_000)) 43 ms 373 ms 8.7×
fib(35) 56 ms 110 ms 2.0×

My MRI and MRI+YJIT timings match the published table closely — 495 ms / 110 ms against its 480–500 ms / 100–110 ms — so the two harnesses are measuring the same thing; the AOT row is the only one that diverges. The site now names both measured ratios and explains the gap between them: recursion keeps the call overhead that the loop case removes. It also now says that only methods the AOT backend can lower benefit at all.

My first attempt at this measurement used fib(28) and returned 0.00s for all four runtimes — a probe that cannot discriminate. The numbers above come from the project's own benchmark inputs, where the workload dominates process startup.

Conformance

21,982 / floor 21,970 → 22,488 / floor 22,475, from three runs that agreed exactly. The stated share of examples that ran and passed rises from 91.4 % to a measured 93.3 % (22,488 of 24,116). Added the scope that was missing: only language/ and core/ are swept, so library/, optional/ and security/ are not run and this is not a percentage of Ruby.

Dropped the run-to-run jitter narrative — three full sweeps here gave identical totals, and the spec file blamed for it returned identical counts in five consecutive runs.

Two claims that overstated what the code does

  • "A complete Ruby, written in Go" is not what the measurement supports. The headline is now "A Ruby you can embed, written in Go."
  • The "Truly embeddable" card promised an object model "callable straight from Go". It is not: the public API is one function, ruby.Run(src, out), and calling a Ruby method from Go is not exposed. The card now says what you actually get.

Smaller fixes

  • The hero terminal showed invented output for rbgo build --closed app.rb -o app. The command does work with that argument order — verified — so it stays, now with the three lines it really prints, including the 172.5 MiB binary size it had omitted.
  • The six-arch claim is qualified: amd64 and arm64 run per pull request; riscv64, loong64, ppc64le and s390x are validated on a nightly schedule, off the PR path. The previous text implied all six gate every change.
  • 178 modules across 176 orgs survived checking — it reproduces under the counting command the README documents.

🤖 Generated with Claude Code

…PI card

Re-measured on 3e8e3cc (darwin/arm64) against MRI 4.0.5 on the same host.

- "rbgo+AOT beats MRI+YJIT 18-24x on loop/fib" does not hold, by two independent
  readings. The repository's own BENCHMARKS.md table gives AOT 10 ms vs YJIT 360 ms
  on loop (36x) and AOT 20 ms vs YJIT 100 ms on fib (5x) -- neither is 18-24x, so the
  figure does not follow from the numbers it cites. Re-running the project's own
  bench/loop.rb and bench/fib.rb here with hyperfine: AOT 43 ms vs YJIT 373 ms on
  loop (8.7x) and AOT 56 ms vs YJIT 110 ms on fib(35) (2.0x). My MRI and MRI+YJIT
  timings match the published table almost exactly (495/110 ms against its 480-500/
  100-110 ms), so the harnesses are comparable; the AOT row is where they diverge.
  The site now names both measured ratios and says recursion keeps the call overhead
  the loop case removes.

- Conformance: 21,982 / floor 21,970 -> 22,488 / floor 22,475, and the share of
  examples that ran rose from a stated 91.4% to a measured 93.3% (22,488 of 24,116).
  Added the scope that was missing everywhere: only language/ and core/ are swept,
  so library/, optional/ and security/ are not run and this is not a percentage of
  Ruby.

- Dropped the run-to-run jitter narrative: three full sweeps here gave identical
  totals, and the spec file blamed for it returned identical counts in five runs.

- "A complete Ruby, written in Go" overstates what the measurement supports; the
  headline is now "A Ruby you can embed".

- The "Truly embeddable" card promised an object model "callable straight from Go".
  The public API is one function, ruby.Run(src, out); calling a Ruby method from Go
  is not exposed. The card now says so.

- The hero terminal showed invented output for rbgo build --closed. The command does
  work with that argument order, so it is kept, now with the real three lines it
  prints -- including the 172.5 MiB binary size it had omitted.

- Six-arch claim qualified: amd64 and arm64 run per pull request; riscv64, loong64,
  ppc64le and s390x are validated nightly, not on the pull-request path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 85b1e77 into main Sep 26, 2026
2 checks passed
@tannevaled
tannevaled deleted the wave34-docs-go-embedded-ruby.github.io branch September 26, 2026 14:30
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.

1 participant