Skip to content

deps(regex): take perex 0.1.11 (perex#3 matcher) under a one-time publish-age override - #11548

Merged
proggeramlug merged 4 commits into
mainfrom
perf/regex-perex-adopt
Sep 28, 2026
Merged

proggeramlug merged 4 commits into
mainfrom
perf/regex-perex-adopt

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Part of #10166

Moves Perry's regex engine from perex 0.1.9 (what main pins) to 0.1.11, which carries PerryTS/perex#3: package-shaped repeats and character classes leave the matcher's per-character phase loop.

  • 0.1.9 → 0.1.10 adaptation (kept). Search::run now fails with RunError { error, remaining_work, buffers }. Both call sites in perex_runtime.rs record the work a failed run left instead of keeping the entry budget. Nothing observes this today, because WORK is usize::MAX on these paths.
  • 0.1.10 → 0.1.11. No public API change (the perex diff touches only pub(super) items), so this step is a version bump.

Publish-age override (owner-approved, one time)

perex 0.1.11 was published 2026-09-27T21:13:35Z, inside the 7-day global-min-publish-age soak in .cargo/config.toml. The owner approved a one-time override for this version on 2026-09-28. This follows the turnloop precedent (#10354):

  • Cargo.lock was resolved once with CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow (cargo update -p perex --precise 0.1.11). The only lock change is perex's version and checksum.
  • The perex = "0.1.11" comment in Cargo.toml records the approval date, the publish time, the release commit (80845f5310, tag v0.1.11), and the sha256 that Cargo.lock pins: 4cacad0d8fd77338345abb71e4f8372ce93bf0e9205d845940f8e789b3fc98a8. I checked that checksum against https://crates.io/api/v1/crates/perex/0.1.11. The override lapses on its own on 2026-10-04.
  • SOAK_DAYS, .cargo/config.toml and the soak surfaces are unchanged. No gate checks Cargo.lock publish ages: soak-gate (scripts/soak/soak.mts --check) only checks config parity, and the soak skill's dated exclusions exist only for pnpm. So there is no exclusion entry to add. The Cargo.toml comment is the reviewable record.
  • tests/release/packages/next-app-route/provider/Cargo.lock still pinned perex 0.1.9. It moves to 0.1.11 under the same override. Re-resolving it also adds perry-abi, which the provider's runtime already depends on on main, but that lock was older than the dependency.

Measurements

Host: perrymaster (AMD Ryzen 7 7700X, shared, load 20–70 during runs; instruction counts do not depend on load). Both arms use plain --release, cargo build -p perry -p perry-runtime-static -p perry-stdlib-static, with PERRY_NO_AUTO_OPTIMIZE=1 and PERRY_RUNTIME_DIR pinned per arm. The main arm is origin/main at 2d1f1d7. The branch arm is this branch before its final rebase onto be39bbf; the 17 commits in between touch GC call-effects tables and the object spill store, not regex. I verified the arms differ: the runtime .a sha256 changed (a23a544f… → 905281d5…) and the embedded crate paths read perex-0.1.9 and perex-0.1.11 respectively. Instructions come from perf stat -e instructions:u as a two-N differential, per iteration, taken under /tmp/perry-bench-lock.d.

Package workloads (scripts/package_bench.py run --arms node,perry --modes instr,rss, Node 26.5.1). Every Perry output, in both arms, was byte-identical to Node's:

workload node main this PR Δ
jsonwebtoken/decode 35,352 198,925 77,478 −61.1%
uuid/v4 6,619 63,523 33,111 −47.9%
uuid/v7 18,296 88,407 58,020 −34.4%
nanoid/generate 2,870 45,065 31,388 −30.4%
uuid/v5_parse 48,480 214,103 153,312 −28.4%
validator/batch 952,054 20,234,645 19,703,179 −2.6%
dotenv/parse 203,917 2,877,286 2,805,877 −2.5%
moment/parse_format 116,885 2,412,397 2,353,398 −2.4%
decimal.js/parse_sum 1,782,722 39,791,342 38,965,198 −2.1%
node-cron/validate_parse 427,170 4,204,151 4,131,497 −1.7%
validator/sanitize 32,990 396,650 391,180 −1.4%
moment/diff_duration 95,733 1,763,447 1,741,381 −1.3%
decimal.js/arith_chain 236,941 3,794,684 3,784,680 −0.3%
date-fns/format_add 84,876 938,631 936,533 −0.2%
dayjs/diff_startof 187,236 6,015,659 6,003,987 −0.2%
node-cron/match, date-fns/diff_interval ±0.0%
dayjs/parse_format 65,229 1,417,892 1,421,387 +0.2%
commander/parse_argv 195,351 3,742,748 3,755,994 +0.4%
control/bare_loop, control/prop_read 26 / 119 26 / 119 0.0%

The only regression outside noise is commander/parse_argv at +0.4%, about 13k instructions per iteration. All three reps agree (n2 is 19.73–19.74G on main against 19.80–19.81G here), so it is real, but it is small. dayjs/parse_format's +0.2% is inside that workload's rep spread.

Microbenchmarks, instructions per call (two-N, each N the median of 3; output identical to Node):

probe main this PR Δ
uuid REGEX.test (/^(?:[0-9a-f]{8}-…)$/i) 23,553 8,199 −65.2%
jws JWS_REGEX.test, 155-char token 99,325 15,629 −84.3%
/^\d+$/.test 5,295 5,010 −5.4%
bare-loop control 92.0 92.0 0.0%

Peak RSS (/usr/bin/time, one n2 run, 5 reps interleaved main/branch, median): no workload moves outside its own rep spread. The largest medians are date-fns/format_add −10.9%, moment/parse_format −13.6%, moment/diff_duration +7.2%, validator/sanitize +6.9%, nanoid +4.8% and validator/batch +4.2%, but the reps of each arm overlap by tens of percent. I re-ran validator/batch, validator/sanitize and decimal.js/parse_sum at 10 reps, and they came out −0.2%, +0.1% and +0.2%. uuid, jsonwebtoken and dotenv are within ±1%. Micro RSS: uuid +0.1%, jws +7.5%, \d+ −18.2%, all inside the spread of 14–24 MB. The matcher's scratch is unchanged, so no RSS change is expected, and none is measurable here.

Tests (perrymaster)

  • RUST_TEST_THREADS=1 cargo test --release -p perry-runtime --lib -- perex split replace regex: 278 passed, 0 failed.
  • Gap A/B against a pristine main build, run_parity_tests.sh with PERRY_SKIP_BUILD=1 PERRY_NO_AUTO_OPTIMIZE=1, filters regex, regexp, split, replace, match, Node 26.5.1. 49 unique tests, including test_gap_regex_engine_package_shapes. Branch: 49/49 PASS. Main: 48 PASS, 1 COMPILE_FAIL (test_gap_regex_replace_dyn_regex_with_http). That compile failure is a harness artifact of the main arm, not a regression this PR fixes: it links the on-demand libperry_ext_http.a archive, which my copied main-arm runtime dir did not include. The PR body before this rewrite reported the same COMPILE_FAIL on main.
  • scripts/gc_call_effects/regen.sh linux-x86_64 --check on the rebased head (fresh build): the table is identical to the archives, so no regeneration is needed.
  • cargo fmt --all -- --check: clean. scripts/check_file_size.sh: OK.
  • scripts/run_lint_gates.sh (SKIP_COMPILE_GATES=1): 99 of 101 script gates passed. The 2 failures are known-red and not caused by this PR: Public benchmark evidence freshness (red on main) and cargo xwin check (cargo-xwin is not installed on perrymaster).

Not run: the full gap sweep, the auto-optimize arm, macOS, Windows (cargo xwin), cargo test --workspace, and the full perry-runtime test suite (only the regex/split/replace/perex filter). The numbers were measured on the pre-rebase head. The rebase onto be39bbf brought in no regex changes, and after it I re-ran only the build and the call-effects check.

Summary by CodeRabbit

  • Performance
    • Regex and package workloads use fewer instructions following the update. Peak memory usage showed no change beyond run-to-run variation.
  • Bug Fixes
    • Failed regex searches now account for work already consumed when reporting remaining work. This does not affect current searches, which use effectively unlimited work budgets.
  • Compatibility
    • Outputs remain byte-for-byte identical to Node 26.5.1.

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: d61b35c4-95ec-4f95-baa6-3a16aaaa0821

📥 Commits

Reviewing files that changed from the base of the PR and between be39bbf and 8803718.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • tests/release/packages/next-app-route/provider/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • Cargo.toml
  • changelog.d/11548-perex-0111-package-regex-shapes.md
  • crates/perry-runtime/src/regex/perex_runtime.rs

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

The workspace dependency changes from perex 0.1.9 to 0.1.11. Both regex search paths now update the caller’s work budget from the remaining work when Search::run fails, before returning the mapped error.

Changes

perex upgrade and search handling

Layer / File(s) Summary
Dependency upgrade and failed-search handling
Cargo.toml, crates/perry-runtime/src/regex/perex_runtime.rs, changelog.d/11548-perex-0111-package-regex-shapes.md
The workspace dependency changes to perex 0.1.11. Both failed-search paths update the caller’s budget before mapping and returning the error. The changelog records the upgrade, reported measurements, and verification details.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to 88037

The dependency and lockfiles are consistent, and no actionable issue remains. This change is mergeable after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 88037

An exact-pinned regex release is being adopted before the usual waiting period. Existing regex execution controls remain in place, and no new entrypoint or verified security defect was found, but the early adoption leaves some uncertainty about the new engine behavior.

Retained concerns

  • Low · security · inferred: The one-time resolution override admits the new regex-engine release before the workspace’s seven-day publish-age window has elapsed. Pinning and documenting the artifact bound the exception to one version, but do not provide the waiting period that the normal control supplies.
Security review details

Security Blast Radius

  • inferred — Regex patterns and input supplied through the existing runtime API reach the upgraded matcher. The observed exposure is that execution path and the pinned package, not a newly exposed service or public API.

Trust Boundaries and Controls

  • observed — The publish-age exception affects dependency selection; it does not remove the existing search memory and polling controls. The lockfile fixes the selected artifact’s checksum, although that alone does not establish the artifact’s safety.

Resilience and Maintainability Implications

  • inferred — The scratch-fallback budget reset is an existing accounting qualification, not an established regression from this PR. Its effect on finite-budget calls with the new matcher remains unverified; the ordinary regex path starts with an effectively unbounded work allowance.

Hardening Proposals

  • proposed — Before exposing the early release broadly, independently verify the pinned package artifact and exercise new matcher workloads through cancellation, scratch fallback, and finite-budget recovery paths.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 1 files. (2 skipped: 2… 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.
Title check ✅ Passed The title clearly identifies the primary change: updating the regex dependency to perex 0.1.11 under a one-time publish-age override.
Description check ✅ Passed The description provides a detailed summary, concrete changes, issue reference, test results, measurements, known limitations, and override details. It does not use every template heading or include t…
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 1 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@proggeramlug

Copy link
Copy Markdown
Contributor Author

perex 0.1.11 is published (crates.io, tag v0.1.11, commit 80845f531 = perex#3 merged + version bump). It clears Perry's 7-day publish-age soak around 2026-10-04 21:40Z. Then this PR only needs the version bump from 0.1.10 to 0.1.11 and a re-measure. Measured with perex#3 patched in locally on top of #11543: jsonwebtoken decode −52%, uuid v4 −48%, v7 −30%, v5 parse −24%, nanoid −20%, RSS within 1%.

Ralph Küpper and others added 4 commits September 28, 2026 11:07
perex 0.1.10's `Search::run` fails with `RunError { error, remaining_work,
buffers }`. Both call sites in `perex_runtime.rs` now set the budget from the
failed run's remaining work, where they used to keep the entry budget and
under-count what the failed call spent. Nothing observes that today, since
WORK is usize::MAX on these paths.

This is the adaptation the perex release carrying PerryTS/perex#3 (the
package-shaped repeat and class fast paths) needs. Taking that release is then
a version bump.
perex 0.1.11 carries PerryTS/perex#3: package-shaped repeats and classes
leave the per-character phase loop. It has no public API change from
0.1.10, so this is a version bump.

0.1.11 was published 2026-09-27T21:13:35Z, inside the 7-day
global-min-publish-age window. The owner approved a one-time override on
2026-09-28 for this version only. Cargo.lock was resolved once with
CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow, and the Cargo.toml comment
records the approval, the publish time, and the sha256 the lock pins
(4cacad0d...98a8), checked against the crates.io API. The soak window and
.cargo/config.toml are unchanged.

The Next App Route provider lock moves from perex 0.1.9 to 0.1.11 as well.
Re-resolving it also adds perry-abi, which the provider's runtime already
depends on on main but its lock predated.
@proggeramlug proggeramlug changed the title deps(regex): take perex 0.1.10; ready for the perex#3 matcher release deps(regex): take perex 0.1.11 (perex#3 matcher) under a one-time publish-age override Sep 28, 2026
@proggeramlug
proggeramlug marked this pull request as ready for review September 28, 2026 11:25
@proggeramlug
proggeramlug merged commit 295473c into main Sep 28, 2026
62 of 64 checks passed
@proggeramlug
proggeramlug deleted the perf/regex-perex-adopt branch September 28, 2026 13:29
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