Skip to content

perf: inline number strings, streamline Map guards and UUID formatting - #11643

Merged
proggeramlug merged 14 commits into
mainfrom
claude/zealous-noether-453kqt
Oct 3, 2026
Merged

proggeramlug merged 14 commits into
mainfrom
claude/zealous-noether-453kqt

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Current head 65cbfce71e8b4d26c781f8e04ac5d09150550433 incorporates the landed main CI repairs: the diagnostic census has a five-minute step limit, and full-tier require fixtures prepare coherent providers before their bounded execution. The merge changes only five workflow/protocol-test/changelog files; every Rust source, manifest, lockfile and Cargo configuration is byte-identical to the validated f57f5d90984cfe6068e709e8d07e6ddebadf8f06 head. All eleven removed regex/nursery paths remain byte-identical to current main. At the refreshed head, all eleven provider protocol tests, eighteen GC wiring controls and nine wired gates pass; whitespace checks pass.

The previous native root job 110697725348 succeeded in both required checks and its diagnostic census, but the census consumed 12m56s and the whole job hit its 90-minute limit during Post Cache cargo. Its cancelled whole result is not approval. The new head needs actual successful whole shadow and native root jobs and remaining CI acceptance. Product/unit/Node/main-stdlib comparisons below were obtained at the earlier scoped head; source identity is established above, but no new-head whole CI result is claimed.

This PR now contains three scoped improvements:

The held regex scratch/external-byte accounting and adaptive nursery changes have been removed. All eleven affected regex, collector-policy, test, documentation and changelog paths are byte-identical to main 47a0c7bf1795bc5e1f85d6c96c0f52037ff1972b. The root-holder inventory preserves every main entry and source pin and adds only three scalar/test holder entries. No RSS-versus-compute tradeoff is included in this scoped change.

Validation at f57f5d90984cfe6068e709e8d07e6ddebadf8f06:

  • Locked release compiler and matching runtime/stdlib static libraries built with LLVM 22.1.4.
  • Both compiled gap fixtures match pinned Node 26.5.1, including all 109,999 integers in the inline range, fallback/boundary cases, ASCII/non-ASCII indexing, and Map/Set/Date/Array own overrides after global population.
  • Three number codegen tests, four UUID tests, and the full serial runtime suite passed (4,759 passed, five ignored).

The full serial stdlib suite has 243 passes and one pre-existing failure in runtime_thread_exit_tests::symbols_tests::thread_exit_releases_the_threads_dom_exceptions at symbols_tests.rs:484 (a dead thread's DOMException address outlived its heap). An independent whole-suite run at current main 47a0c7bf1795bc5e1f85d6c96c0f52037ff1972b, using the same locked release command, package and environment, produced exactly the same 243 passes and single failed test/assertion; the test source is byte-identical. No additional stdlib failures were introduced.

Full local script lint finished: 110 of 111 checks passed; only the known Public benchmark evidence freshness check failed. The compile tier and two CI-only commands were explicitly skipped; the locked release product build and targeted codegen units above were run separately. The owner authorized removing the held bundle and landing the valid scoped fixes; the bundle-related hold can now be lifted for this published head. Fresh CI remains required.

The instruction counts in the retained changesets are the original author's historical measurements; they have not been remeasured at this revised head. CI approval requires new-head checks, including successful whole gc-root-dominance and gc-root-dominance-statepoints jobs. The old skipped jobs provide no approval for this head.

Historical CI triage at f57f5d90984cfe6068e709e8d07e6ddebadf8f06: native-backend job 110697759307 completed with 1,844 passes, five failures and one ignored test. All five failed property-read IR assertions match the independently completed main job 110249849088, including the previously reviewed inherited-to-generic test-name rename; the test source is byte-identical to the previously reviewed integration head. Lint job 110697808524 failed only Public benchmark evidence freshness. These are specific main-side failure attributions, not green CI results. The previous shadow job passed; the previous native whole job later cancelled during cache saving. Neither history replaces new-head CI approval.

Current-head GC update: both whole jobs completed successfully at 65cbfce71e8b4d26c781f8e04ac5d09150550433: shadow root dominance and native statepoints root dominance. All executed steps in both jobs succeeded. Remaining CI failures and pending jobs still require acceptance; this does not claim overall CI is green.

#10762: String(n), `${n}`, n.toString() and "" + n on a number operand
build a small integer's SSO text inline at the call site (fixed-point
digit split, exact for every value under 100000), with the runtime call
on a cold arm. `const s = String(n)` / `${n}` / "" + n (a + with a string
literal) now record a runtime-derived String proof, so s.charCodeAt and
the other string lowerings no longer fall to the generic method site, and
the inline charCodeAt reads an ASCII SSO receiver's byte from the value
instead of materializing a heap copy.

#10697: populating globalThis installed builtins onto intrinsics through
the exotic-store gauntlet and armed PERRY_OWN_NAMED_PROP_INSTALLED, which
sent every proven Map/Set/Date builtin call through the ~600-instruction
hasOwn predicate. The runtime's own builtin definitions now arm it only
for Map/Set/Date (or unreadable) owners; the universal dispatcher reads a
separate flag every install still arms. Small-map lookups also answer a
bit-identical key of any type from the inlined hot lane.

#11549: the lent regex scratch cell grows past 32 registers, and
operation-scoped regex Buffers are accounted as transient external bytes,
so a large pattern in a loop no longer feeds released-bytes pressure into
full collections. The scavenge nursery now powers on at a quarter of its
base and climbs back on survivor influx, which keeps peak RSS flat now
that the phantom fulls are gone; the #8122 census seeds at half the
power-on cap.

#10523: the UUID formatter writes through a constant position table and
the stdlib copies its bytes without re-validating them as UTF-8.

No version bump.
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

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

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 1c4cb263-daae-4cea-9bbd-63b8e27f98be

📥 Commits

Reviewing files that changed from the base of the PR and between 38433c4 and 954c629.

📒 Files selected for processing (3)
  • crates/perry-codegen/src/expr/mod.rs
  • crates/perry-runtime/src/object/mod.rs
  • scripts/gc_runtime_root_holders.json

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


📝 Walkthrough

Walkthrough

The pull request updates numeric string conversion, small-Map lookup, builtin install tracking, regex scratch and garbage collection, and UUID formatting. It adds supporting tests, documentation, and changelog entries.

Changes

Inline number-to-string and character access

Layer / File(s) Summary
Numeric conversion lowering
crates/perry-codegen/src/expr/*, crates/perry-codegen/src/lower_call/property_get/number_string.rs, crates/perry-codegen/src/lower_string_concat.rs, crates/perry-codegen/src/type_analysis/refine.rs, test-files/test_gap_10762_inline_number_to_string.ts, changelog.d/11643-inline-number-to-string.md
Proven numeric operands in the supported range use inline conversion; other values retain runtime fallbacks. Type analysis recognizes additional string-producing initializers. Tests cover conversion forms, boundaries, and runtime values that differ from their annotations.
ASCII SSO character access
crates/perry-codegen/src/lower_string_method/char_code_at.rs, crates/perry-codegen/src/expr/number_to_string_inline_tests.rs, test-files/test_gap_10762_inline_number_to_string.ts
charCodeAt reads in-range ASCII bytes directly from SSO payloads. Other SSO cases use the slow path. Tests cover fast-path lowering and character access cases.

Small-Map lookup

Layer / File(s) Summary
Small-Map identity lookup
crates/perry-runtime/src/map.rs, crates/perry-runtime/src/map/string_key.rs, changelog.d/11643-map-own-override-flag-builtin-installs.md
Small maps check identity-matching keys of any type in the hot lane. Unresolved non-number keys continue to the cold path. Tests count cold lookups for identity matches, content-equal keys, and misses.

Builtin own-override tracking

Layer / File(s) Summary
Builtin install guard tracking
crates/perry-runtime/src/object/*, test-files/test_gap_10697_own_override_after_global_population.ts, changelog.d/11643-map-own-override-flag-builtin-installs.md
Builtin-definition installs on readable owners other than Map, Set, or Date do not arm the emitted-guard flag. Install history remains recorded separately. Install call sites pass owner addresses, and tests cover builtin installs and later instance overrides.

Regex scratch and garbage collection

Layer / File(s) Summary
Regex scratch reuse and transient accounting
crates/perry-runtime/src/regex/*, crates/perry-runtime/src/gc/policy.rs, crates/perry-runtime/src/gc/tests/runtime_roots/perex_*, test-files/test_gap_11549_regex_large_register_scratch.ts, changelog.d/11643-regex-scratch-gc-pressure.md
Lent regex scratch grows to support up to 4096 registers. Operation-scoped buffers use transient external-byte accounting. Tests cover scratch reuse, owned-buffer use, and live-byte accounting.
Nursery cap and allocation census
crates/perry-runtime/src/gc/tenuring.rs, crates/perry-runtime/src/gc/tests/copying/adaptive_tenuring.rs, crates/perry-runtime/src/gc/tests/triggers.rs, docs/src/internals/garbage-collector.md, scripts/gc_runtime_root_holders.json, changelog.d/11643-regex-scratch-gc-pressure.md
The nursery cap starts at one quarter of its base and adjusts through debounced influx thresholds. The allocation census seed point is half the power-on cap. Tests and documentation describe the updated cap behavior.

UUID formatting

Layer / File(s) Summary
Fixed-layout UUID bytes
crates/perry-uuid/src/lib.rs, crates/perry-stdlib/src/crypto/random.rs, changelog.d/11643-random-uuid-format.md
Hyphenated writes hexadecimal digits at fixed positions and exposes its byte array. UUID string creation uses those bytes directly. Tests check the formatted layout and byte equivalence.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Refactor

Suggested reviewers: claude

Merge Risk: ⚪ Minimal · up to 954c6

The selected changes are mergeable after normal checks; no unresolved issue is established.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 954c6

Several shared behaviors change, but the examined controls remain in place and no exploitable regression was established. Broader integration behavior remains unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The security-relevant exposure is runtime-wide behavior of compiled code using guarded builtin calls and regex or allocation-heavy workloads, rather than a newly exposed code-generation entrypoint.

Trust Boundaries and Controls

  • observed — The general method dispatcher uses the install-history flag, while the emitted fast-path guard uses the more selective flag. This preserves a check for user-defined own methods despite the narrower builtin-install policy.

Resilience and Maintainability Implications

  • observed — Allocation and drop move the regex transient live-byte count in opposite directions; the accounting change does not itself trigger collection while a caller holds heap views.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.51% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 82 functions across 30 files. (1 skipped:… 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 summarizes the three retained performance changes: inline number-to-string conversion, Map guard behavior, and UUID formatting.
Description check ✅ Passed The description provides a detailed summary, lists the changes and related issues, and documents validation results, known failures, and pending CI acceptance. It does not use every template heading o…
Full details: Docstring Coverage

Explanation

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

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • 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.

… user

Without the feature the regex module is compiled out and both functions
were dead code, which the -D warnings workspace check rejects. Re-pins
PASS1_MARKED's gc/policy.rs source hash.

Copy link
Copy Markdown
Contributor Author

lint is red at the public-baseline step (benchmarks/ci_public_baseline_check.py: "public artifact benchmark inputs changed"). This failure doesn't come from this PR:

  • The PR touches none of SOURCE_PATHS/HARNESS_PATHS in benchmarks/public_baseline.py (no Cargo.toml, no benchmarks/ edits).
  • The same check exits 2 on current main (5bd0aba9) and on each of the previous 8 main commits that touched Cargo.toml, back to at least 5a6310af. The fingerprint normalizes the workspace version, so the drift comes from real manifest changes on main, such as the perex dependency bumps in d9ec9e17/094b3cf1.

No fix exists to port. The artifact has to be regenerated with ./benchmarks/run_public_baseline.sh on the quiet benchmark host (~2 h), which this PR can't do. I searched open PRs and didn't find one that regenerates it. The rest of this PR's checks are still running, and I'll handle anything they turn up.


Generated by Claude Code

…r-453kqt

# Conflicts:
#	scripts/gc_runtime_root_holders.json
…r-453kqt

# Conflicts:
#	scripts/gc_runtime_root_holders.json
…r-453kqt

# Conflicts:
#	scripts/gc_runtime_root_holders.json

Copy link
Copy Markdown
Contributor Author

gap-suite (4) and gap-suite (6) are red on 954c6292, each with one regression. Neither comes from this PR; main has the same failures.

  • test_gap_11499_class_object_static_write
  • test_gap_10480_define_property_generic_descriptor_accessors

Cause: a class static setter receives the class object instead of the assigned value. For example, static set sv(v) { C._v = v * 10 } followed by C.sv = 2 leaves C._v as NaN. I reproduced this with a local perry-dev build of main at 41de9c5f, which is this PR's merge base, with none of this PR's changes. Both tests fail there exactly as they do on this branch, and a build from before #11651 prints 20. The regression came in with that main range (most likely #11651, "class static accessors are accessor properties of the class function object"). This PR does not touch class statics or accessor dispatch.

Fix: none that I've verified yet. #11667 reworks static storage, but I haven't confirmed that it fixes the setter argument. Once a fix lands on main, I'll merge main in again. lint still fails only on the stale public baseline, as in my earlier comment.


Generated by Claude Code

…r-453kqt

# Conflicts:
#	scripts/gc_runtime_root_holders.json

Copy link
Copy Markdown
Contributor Author

e2e-scoped is red on cbab4afa, but not because of this PR. The failure is in scripts/ci_e2e_scope.py --self-test, which runs before any suite:

these crates/perry-codegen/tests/*.rs suites are in neither SOURCE_SUITE_MAP nor SUITE_EXCLUSIONS: typed_array_update_lowering

main's #11666 (b0bf0ae7) added crates/perry-codegen/tests/typed_array_update_lowering.rs without registering it. The self-test exits 1 on main at b0bf0ae7 alone, so every PR that merges current main fails here. main has no fix yet, and one isn't in this PR's scope, so I'm not widening the diff for it.

Proposed patch for main; it's one line, and I checked that the self-test prints ok with it:

--- a/scripts/ci_e2e_scope.py
+++ b/scripts/ci_e2e_scope.py
@@ _CODEGEN_SUITES
     "typed_array_rmw_8692",
+    "typed_array_update_lowering",
     "typed_shape_declared_at_allocation",

Once this lands on main, I'll merge main in again. The other two known red checks are unchanged: lint's stale public baseline, and the two static-setter gap regressions from main described above.


Generated by Claude Code

Resolve scripts/gc_runtime_root_holders.json by taking main's PASS1_MARKED
text, re-appending this branch's #11549 audit note, and pinning
gc/policy.rs to the merged file (it differs from main only by this
branch's audited hunks).

Port own_override_builtin_install_tests to main's #11654 closure ABI:
js_closure_alloc now takes a static JsFunctionInfo, and bodies take the
#11637 receiver parameter.

Copy link
Copy Markdown
Contributor Author

self-test-checkers fails on 2635a8b7, but the failure is on main, not in this PR. The failing step is scripts/check_thread_locals.py:

crates/perry-runtime/src/async_hooks.rs: lost raw thread_local! declarations (7 recorded, 6 found)
crates/perry-runtime/src/node_stream_constructors.rs: lost raw thread_local! declarations (3 recorded, 2 found)

This PR doesn't touch either file or the ratchet. main removed those declarations without re-recording scripts/thread_local_cold_allowlist.json. The check exits 1 on main at both 6ce52044 and the current head d7df6e75, and I haven't seen a fix for it.

Proposed patch for main: run scripts/check_thread_locals.py --update. It only lowers counts, and the check then reports OK: 521 hot declarations.

-  "_hot_declarations": 528,
+  "_hot_declarations": 521,
-    "crates/perry-runtime/src/async_hooks.rs": 7,
+    "crates/perry-runtime/src/async_hooks.rs": 6,
-    "crates/perry-runtime/src/node_stream_constructors.rs": 3,
+    "crates/perry-runtime/src/node_stream_constructors.rs": 2,

Once this lands on main, I'll merge main in again. e2e-scoped should now be green, since main's #11675 registered the suite. lint still fails on the stale public baseline, and the gap suite still fails on main's static-setter bug. Both are covered in my earlier comments.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

lint now fails in a second step, scripts/class_id_collisions.py, reporting CLASS_ID mirror drift:

  • 0x00741c77 in crates/perry-runtime/src/object/static_shapes_tests.rs:225
  • 0x7d018001 in crates/perry-runtime/src/object/class_registry/state.rs:1345

This PR doesn't cause it; the drift is on main:

  • CI runs lint on this PR merged with current main.
  • The script passes on this branch's head, 2635a8b7.
  • It exits 1 on main at d7df6e75 alone.
  • This PR doesn't touch either file.

I haven't found a fix on main yet. Once one lands, I'll merge main in again. The public-baseline step in the same job still fails, as in my earlier comment.


Generated by Claude Code

…r-453kqt

# Conflicts:
#	scripts/gc_runtime_root_holders.json

Copy link
Copy Markdown
Contributor Author

On 4fceef9c the static-setter tests pass now that main's #11672 is merged in. Three new gap regressions showed up in their place, and none of them comes from this PR. I reproduced all three on a local perry-dev build of main alone at 7fa094cb, which is the commit this PR merges:

test shard main @ 7fa094cb without this PR
test_gap_sloppy_this_bound_once 3 throws Cannot assign to read only property 'extra' of object '#<Object>' from mutate.call(1), where Node (strict ESM via the root "type": "module") throws Cannot create property 'extra' on number '1'; this branch's build prints the identical wrong error
test_gap_node_redis_from_source 3 FAILED: #<perry:private-member:64:#validateOptions> is not a function instead of the command transcript
test_gap_mongodb_from_source 5 prints the version line, then Uncaught (in promise) TypeError: @@iterator is not a function in MongoClient parseOptions, exit 1

All three look like fallout from main's recent receiver and class-static reworks (#11637, #11667 and #11679). None of them touches code this PR changes. The two newer main commits (#11682, #11683) don't look like fixes for them. I'll merge main again once fixes land. The earlier main-side failures I reported are unchanged: the lint public baseline, lint CLASS_ID mirror drift, and the self-test-checkers thread-local ratchet.


Generated by Claude Code

@proggeramlug proggeramlug added the run-extended-tests Opt PR into compile-smoke/parity/doc-tests/drizzle-mysql-smoke label Oct 1, 2026
@proggeramlug proggeramlug changed the title perf: inline number-to-string, fix own-override flag arming for Map/Set, regex scratch GC pressure, faster randomUUID perf: inline number strings, streamline Map guards and UUID formatting Oct 2, 2026
@proggeramlug
proggeramlug merged commit e054b86 into main Oct 3, 2026
14 of 17 checks passed
@proggeramlug
proggeramlug deleted the claude/zealous-noether-453kqt branch October 3, 2026 04:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-extended-tests Opt PR into compile-smoke/parity/doc-tests/drizzle-mysql-smoke

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants