Skip to content

perf(codegen): make -Os the default native optimization level - #8457

Merged
proggeramlug merged 1 commit into
mainfrom
perf/size-opt-default-on
Aug 20, 2026
Merged

perf(codegen): make -Os the default native optimization level#8457
proggeramlug merged 1 commit into
mainfrom
perf/size-opt-default-on

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Summary

Flip PERRY_LL_SIZE_OPT so unset means enabled: native compilation now defaults to
-Os. PERRY_LL_SIZE_OPT=0 / off / false / no restores -O3.

#8418 added the knob opt-in "while corpus calibration continues". This is that calibration.

Why: -Os costs no measurable runtime

Measured on the quiet M1 mini under the sweep's bench lock — interleaved, output-checked,
verdict CLEAN, load 1.51 -> 1.72:

row Δ best Δ median disjoint?
churn +0.5% +0.7% no
cycles -0.2% -0.1% no
fib40 +0.0% -0.1% no
interp +0.8% +0.8% no
iso_miss +0.6% +0.8% no
tree_wide +0.0% +0.0% no

Nothing disjoint; everything within 0.8%.

I first measured this on a loaded dev box and got swings from -26% to +21% with the sign
flipping between best and median. That was pure contention — the same failure mode that made
#8412's "0.81x Node" claim not survive scrutiny. The mini is the instrument for this.

So the real trade is compile time against shipped binary size, with runtime unaffected:
+21.3% module codegen on a 4,743-module build, for -346.7 MiB beyond #8418's structural
wins. Smaller artifacts for every user are worth a developer-side build cost.

Scope

On small programs -Os changes nothing measurable — hello-world and the corpus binaries
come out the same size either way. The win is specific to dense generated bundles. A
size-driven policy that engages only where oversized units exist would avoid paying compile
time on trivial builds; worth considering as a follow-up, but it does not block making the
better default the default.

Tests

Three existing tests encoded the old default and are updated rather than deleted:

  • compile_plan_defaults_to_o3 -> compile_plan_defaults_to_os
  • compile_plan_records_effective_target_and_native_tuning now expects -Os
  • size_optimization_flag_is_explicit_and_truthy -> size_optimization_is_on_unless_explicitly_disabled,
    pinning that unset/empty/unknown all enable and only an explicit negative disables

Validation

  • perry-codegen --lib — 1107 passed
  • scripts/run_lint_gates.sh — all 50 gates
  • 19/19 sweep corpus byte-exact against the Node oracle with -Os as the default

Note for anyone A/B-ing this: perry builds are not byte-deterministic (the same config
twice produces different bytes), so binary comparison is not a valid check for whether the
flag took effect. compile_plan_defaults_to_os is the direct proof.

@proggeramlug
proggeramlug merged commit 40e2ce8 into main Aug 20, 2026
15 of 17 checks passed
@proggeramlug
proggeramlug deleted the perf/size-opt-default-on branch August 20, 2026 06:23
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