Skip to content

bench/synth: refit four pypy ceilings the startup subtraction moved, and retire a fifth - #1666

Merged
youknowone merged 2 commits into
mainfrom
virtualizable
Sep 3, 2026
Merged

bench/synth: refit four pypy ceilings the startup subtraction moved, and retire a fifth#1666
youknowone merged 2 commits into
mainfrom
virtualizable

Conversation

@youknowone

@youknowone youknowone commented Sep 2, 2026

Copy link
Copy Markdown
Owner

6aabe927ce1 (#1653) made every pyre backend subtract pypy's startup rather than its own, so what a pyre process spends above pypy to reach the first bytecode now stays in the numerator. It refitted 8 ceilings and lengthened 41 fixtures; these five were in neither list, and each sits where 0.053s-0.110s lands on a baseline of comparable size.

Refitting one at a time does not converge — it relocates. exception_loop_warmup was fixed first, and the same job then failed for_iter_conditional_store_bridge, which is what gate and jit-gc-resume-gaps had been failing on all along.

Method

Every number here is read from CI. Nothing was measured locally, and readings from runs created before 6aabe927ce1 are excluded: they subtracted a different quantity and are not evidence about these gates. That leaves 12 runs, pooled across ubuntu/macos/windows and dynasm/cranelift/wasm.

Only unmarked rows are fitted. A ? row carries a granularity buffer worth EXEC_TIME_FLOOR_S over its baseline, which is precisely what lets it print a ratio far above its ceiling without failing. Every one of these fixtures has its widest reading on such a row — windows dynasm or ubuntu wasm — so counting them would fit each gate to a reading that cannot fail it, inflating all five.

A ceiling must cover the widest unmarked reading and derive a floor (ceiling/6, capped at parity) under the narrowest. That fixes a window:

fixture unmarked band n window ceiling
exception_loop_warmup 2.0x – 4.9x 55 4.9 – 12.0 4.1 → 6.5
for_iter_conditional_store_bridge 1.6x – 5.1x 55 5.1 – 9.6 4 → 7
condexpr_heap_const_merge 2.2x – 6.6x 54 6.6 – 13.2 4.2 → 9
for_iter_nested_method_inline 0.9x – 3.6x 61 3.6 – 5.4 3.3 → 4.4

The fifth is retired rather than refitted

for_iter_method_branch_inline reads 0.8x to 4.5x over 60 unmarked observations — a factor of 5.6 against a PERF_GATE_FLOOR_DIVISOR of 6. That leaves the window 4.5–4.8: six percent wide, with under three percent of margin at either end. A bound that narrow over that many samples reports the runner, not the code.

The spread is the denominator's. pypy executes this loop in 0.30s on macos and 0.10s on ubuntu, and a ratio is scale-invariant, so a longer trip count cannot close it. synth_perf_gate documents an absent ceiling as a full exemption, which 252 of the 525 synthetic fixtures already are.

Not changed

No trip count, no jit-stats baseline, no fixture output. Lengthening was measured and rejected for exception_loop_warmup: doubling it takes pypy from 0.05s to 0.10s, the 2x bar rather than past it, and a length that clears it with margin puts the windows dynasm leg over a second. Its counters are identical at both lengths (loops_compiled=1, bridges_compiled=2, guard_failures=402) and match the committed baselines.

pyre/check.py --check-headers: 527 headers read.

Summary by CodeRabbit

  • Tests
    • Updated performance benchmark thresholds to better reflect current execution characteristics.
    • Removed one overly restrictive benchmark ratio guard.
    • Benchmark logic and expected validation behavior remain otherwise unchanged.

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: e9abfd95-0a2d-4e7e-95b1-dae05927c7c7

📥 Commits

Reviewing files that changed from the base of the PR and between 9f81966 and ad15102.

📒 Files selected for processing (5)
  • pyre/bench/synth/condexpr_heap_const_merge.py
  • pyre/bench/synth/exception_loop_warmup.py
  • pyre/bench/synth/for_iter_conditional_store_bridge.py
  • pyre/bench/synth/for_iter_method_branch_inline.py
  • pyre/bench/synth/for_iter_nested_method_inline.py
💤 Files with no reviewable changes (1)
  • pyre/bench/synth/for_iter_method_branch_inline.py

Included review availability: Your plan provides up to 2 included reviews per hour; 0 remain after this review.


Walkthrough

Five Pyre benchmark fixtures update their max-pypy-ratio directives. Four thresholds increase, and one directive is removed. Benchmark program logic remains unchanged.

Changes

Benchmark threshold configuration

Layer / File(s) Summary
Update benchmark ratio guards
pyre/bench/synth/condexpr_heap_const_merge.py, pyre/bench/synth/exception_loop_warmup.py, pyre/bench/synth/for_iter_conditional_store_bridge.py, pyre/bench/synth/for_iter_method_branch_inline.py, pyre/bench/synth/for_iter_nested_method_inline.py
Four max-pypy-ratio values increase, and one directive is removed. Benchmark logic is unchanged.

Estimated code review effort: 1 (Trivial) | ~2 minutes

Merge Risk: ⚪ Minimal · up to ad151

This updates synthetic benchmark performance guard thresholds to reflect the revised measurement basis, without changing benchmark behavior or outputs. The current changes are ready to merge.

Poem

A rabbit reads each line,
The patch grows clear beneath the moon,
Small changes hop in place,
Tests guard the garden path,
Reviews bloom before the dawn.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the four PyPy ceiling updates and the removal of a fifth ceiling. It is specific to the benchmark changes, but the wording is somewhat awkward.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch virtualizable

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-03T01:49:05.981779Z ad15102 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit ad15102).
Updated: 2026-09-03T01:58:30.577Z

Files in the reviewed diff
pyre/bench/synth/condexpr_heap_const_merge.py
pyre/bench/synth/exception_loop_warmup.py
pyre/bench/synth/for_iter_conditional_store_bridge.py
pyre/bench/synth/for_iter_method_branch_inline.py
pyre/bench/synth/for_iter_nested_method_inline.py

Codex did not produce a report (exit 1). Last log lines:

`lib-python/stdlib-version.txt`), where PyPy and that CPython genuinely differ.
This is usually NOT a 3.11-vs-3.14 delta but a standing PyPy-vs-CPython
divergence; "CPython did not change in 3.14" is not grounds to refile it under
1 or 2. It qualifies only when the finding carries all four of:
(a) an observable difference — return value, exception type/message/attributes,
    identity, encoding-and-errors contract, or accepted argument shapes;
(b) a cited CPython artefact — a `lib-python/3/...:line` assertion, a measured
    run at the pinned version, or C read at that tag in a named checkout. Not
    docs, not a PEP, not a comment in pyre's own source;
(c) the PyPy `file:line` that decides, showing the two upstreams actually
    differ (if PyPy contradicts itself, pyre following PyPy's own declaration
    is section 4 as ordinary parity);
(d) no PyPy-side JIT/GC/annotator hint governing the value being changed —
    `@jit.*`, `_immutable_*`, `_attrs_`, `make_sure_not_resized`,
    `unrolling_iterable`, `rgc.*`, on the function, its helpers, or the class-
    and module-level bindings they read.
Missing any of (a)-(d), or leaving pyre matching NEITHER upstream on an
adjacent observable of the same decision, keep it in section 1 or 2 and say
which test it failed. Full rule: AGENTS.md "Spec follows CPython 3.14;
implementation follows PyPy".

Scope discipline: before writing the report, run
`git diff upstream/main --name-only -- . ':(exclude)*.jitstats'` and treat that
file list as the authoritative definition of "this patch" (when an authoritative
changed-file list is appended below, use that instead of re-deriving it). The
excluded `*.jitstats` files are `pyre/check.py`'s recorded jit-stats baselines —
generated golden data with no RPython/PyPy counterpart, so no parity finding can
cite one, and a bulk re-record of them is not a change to review. Findings under
sections 1 and 2 MUST cite our-side files from that list; a divergence in any
file NOT in the list is by definition not introduced by this patch — report
it under section 3 instead, or omit it. Verify every section-1/2 citation
against the list before finalizing the report.

---

Output format requirements (so the report can be parsed mechanically and
posted/triaged automatically). Use these four headings VERBATIM, in this
order, and nothing else at heading level 2:

## 1. Regressions to PyPy parity introduced by this patch
## 2. Other mismatches introduced by this patch
## 3. Pre-existing mismatches (already present before this patch)
## 4. Structural adaptations

Under each heading, list every finding as a bullet. For each finding cite the
concrete `our_file.rs:line ↔ rpython_or_pypy_file.py:line` pair and quote the
divergence concisely. If a section has no findings, still emit the heading
followed by a single line `None.` so all four sections are always present.
Do not modify any files; produce the report only.

Authoritative changed-file list for this patch (git diff upstream/main --name-only,
minus 0 generated `*.jitstats` baseline file(s)):
pyre/bench/synth/condexpr_heap_const_merge.py
pyre/bench/synth/exception_loop_warmup.py
pyre/bench/synth/for_iter_conditional_store_bridge.py
pyre/bench/synth/for_iter_method_branch_inline.py
pyre/bench/synth/for_iter_nested_method_inline.py
warning: Codex could not find bubblewrap on PATH. Install bubblewrap with your OS package manager. See the sandbox prerequisites: https://developers.openai.com/codex/concepts/sandboxing#prerequisites. Codex will use the bundled bubblewrap in the meantime.
ERROR: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Sep 7th, 2026 2:28 AM.
ERROR: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Sep 7th, 2026 2:28 AM.

@codspeed-hq

codspeed-hq Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will degrade performance by 31.25%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 4 regressed benchmarks
✅ 6 untouched benchmarks
⏩ 6 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
fib_recursive 2.6 s 4.5 s -42.72%
fannkuch 3.3 s 4.7 s -29.75%
nbody 1.9 s 2.5 s -25.7%
fib_loop 1.2 s 1.6 s -25.29%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing virtualizable (ad15102) with main (9f81966)

Open in CodSpeed

Footnotes

  1. 6 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

… subtraction moved

`6aabe927ce1` made every pyre backend subtract pypy's startup rather than its
own, so the startup a pyre process spends above pypy now stays in the
numerator.  4.1 was fitted before that, and this fixture's pypy execution is
0.05s-0.09s -- one to two times FLOOR_GATE_MIN_BASELINE_S -- so the 0.053s-0.110s
that lands on it is comparable to the whole baseline it divides.  It was not
among the 41 fixtures that commit lengthened or the 8 whose ceilings it refitted.

Readings on run 33651833695, which measures it under the new subtraction for
the first time -- `main`'s own run at 6aabe92 was cancelled:

  ubuntu    cranelift  5.0x   (median of 3; the failure)
            wasm       4.4x
            dynasm     3.3x
  macos     cranelift  3.6x
            dynasm     2.9x
  windows   dynasm     5.0x   (marked `?`: the floor declines this baseline)

6.5 covers the widest with 1.3x to spare, and the floor it derives -- capped at
parity, since 6.5/6 is above 1 -- sits 2.9x under the fastest reading.

Not lengthened.  Doubling the trip count takes pypy's execution from 0.05s to
0.10s, which is the 2x bar rather than past it, and leaves a predicted 4.7x that
needs this refit anyway; a length that clears the bar with margin puts the
windows dynasm leg over a second for one fixture.  The recorded jit-stats are
not what argues against it -- measured at both 7840000 and 15680000 on dynasm
and cranelift, loops_compiled=1, bridges_compiled=2 and guard_failures=402 are
identical, and both match the committed baselines.

The same subtraction leaves siblings in the same position: `gate` and
`jit-gc-resume-gaps` both fail this job on `for_iter_conditional_store_bridge`
at 4.8x and 4.5x against a ceiling of 4, with pypy at 0.04s and 0.06s.  Those
are not touched here.

Assisted-by: Claude
… and retire a fourth

`exception_loop_warmup` was not alone in the position `6aabe927ce1` left it in,
and refitting it alone moved the failure rather than removing it: the same job
then failed `for_iter_conditional_store_bridge`, which is what `gate` and
`jit-gc-resume-gaps` had been failing on all along.

Fitted from 12 CI runs created after that commit -- readings from before it
subtracted a different quantity and are not evidence about these gates.  Only
unmarked rows are used.  A `?` row carries a granularity buffer worth
EXEC_TIME_FLOOR_S over its baseline, which is what lets it print a ratio far
above its ceiling without failing, so counting one would fit the gate to a
reading that cannot fail it; every one of these fixtures has its widest reading
on such a row, on windows dynasm or ubuntu wasm.

Each ceiling has to cover the widest unmarked reading and derive a floor
(ceiling/6, capped at parity) under the narrowest, which fixes a window:

  for_iter_conditional_store_bridge  1.6x-5.1x  n=55  window 5.1-9.6    4   -> 7
  condexpr_heap_const_merge          2.2x-6.6x  n=54  window 6.6-13.2   4.2 -> 9
  for_iter_nested_method_inline      0.9x-3.6x  n=61  window 3.6-5.4    3.3 -> 4.4

`for_iter_method_branch_inline` loses its ceiling instead.  Its unmarked
readings span 0.8x to 4.5x over 60 observations, a factor of 5.6 against a
PERF_GATE_FLOOR_DIVISOR of 6, which leaves the window 4.5-4.8 -- six percent
wide, with under three percent of margin at either end.  A bound that narrow
over that many samples reports the runner rather than the code.  The spread is
the denominator's: pypy executes this loop in 0.30s on macos and 0.10s on
ubuntu, and a ratio is scale-invariant so a longer trip count cannot close it.
`synth_perf_gate` documents an absent ceiling as a full exemption, which 252 of
the 525 synthetic fixtures already are.

`exception_loop_warmup`'s 6.5 from the previous commit is left alone: the wider
sample puts its window at 4.9-12.0, and run 33693600706 measured it at 4.5x
under the new ceiling, where it had failed at 5.0x under the old one.

No trip count, jit-stats baseline or fixture output changes.  pyre/check.py
--check-headers: 527 headers read.

Assisted-by: Claude
@youknowone youknowone changed the title bench/synth: refit exception_loop_warmup's ceiling, which the startup subtraction moved bench/synth: refit four pypy ceilings the startup subtraction moved, and retire a fifth Sep 3, 2026
@youknowone
youknowone merged commit e751747 into main Sep 3, 2026
18 of 21 checks passed
@youknowone
youknowone deleted the virtualizable branch September 3, 2026 05:49
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