Skip to content

perf(json): read traced materialized arrays without redundant resolution - #10064

Closed
proggeramlug wants to merge 3 commits into
codex/json-zero-spacingfrom
codex/json-materialized-read-edge
Closed

proggeramlug wants to merge 3 commits into
codex/json-zero-spacingfrom
codex/json-materialized-read-edge

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Repeated reads from materialized JSON arrays re-entered the general GC header resolver even when their live owner already held the exact traced array edge. The outlined accessor now checks that edge directly, retaining the resolver for growth forwarding and the rooted path for descriptors, holes and construction.

Against frozen R25 on the M1, 1 MB field reads use 15% less CPU and indexed reads use 8–10% less; an independent 11-repetition run reproduces the gains. Full 1/8 MB consumption improves 0.8%/0.7%. Disclosed costs: 20 MB sequential reads have a repeated ~0.5 ns higher median; Unicode stringify has a +3.1% median in the independent recheck. Their observed ranges overlap. Peak retained RSS changes by 0 to +32 KiB.

Validation: 295 serial release JSON tests; all 81 candidate behavior/options checks, positive copying/protected GC witnesses, six matching worker objects and 24 matching native/shadow IR files. Eight archived windows contain 4,196 timed trials, 624 output-verification records and 60 calibration trials. Existing unsuppressed native-root findings, known lazy stringify failures and public benchmark freshness failure remain documented.

The R26 report contains the complete CPU/RSS tables, independent rechecks and source/build fingerprints. Timings use measured source 3aac4d6335da54abeeed73df842decbbe6dd5d71, workspace 0.5.1531, not a release-metadata rebuild or merged main. No GC policy, parse-boundary or lazy-admission change.

Stacked on #10052. Ready for review; optimization work continues without waiting for CI. Normal protected checks and merged-main measurement remain before claiming landing.

@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 088c0c74-56d9-4502-9bf9-45deea692064

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

Landed on main via merge train #10083 (rebase-merged, per-commit authorship preserved).

Your commits are on main starting at 1c6da98ab; the train tree was verified identical to main after the merge (git diff origin/main HEAD --stat empty).

Closing this PR as landed — GitHub cannot auto-close it because the train merges as its own branch.

proggeramlug pushed a commit that referenced this pull request Sep 12, 2026
The local `lint` tier failed two ratchets that the individual PRs did not
run against post-#10064 `main`:

  raw-handle debt: 962 (baseline 945), 4 per-module violations
  string payload-access baseline stale (perry-runtime 352 -> 351)

The debt is real, not a ceiling question. `--no-raise-vs <merge-base>`
refuses a ceiling on a file that was absent at the base and refuses any
per-module raise, so `concat_reverse.rs` (0 -> 5) and the new
`wide_object_membership_tests.rs` (0 -> 9) could not be listed, and
`iterator.rs` (31 -> 32) / `push_pop.rs` (12 -> 14) could not be raised.
Converted all 17 sites to the shape the ratchet exists to enforce:

- `array/concat_reverse.rs`: both `push(...src)` element loops now read
  the source inside `with_const_ptr`, so no address survives the
  `js_array_push_f64` that can move it. The grow path reads the source
  through `across_const` around a `with_mut_ptr` grow, which is where the
  post-allocation re-read belongs.
- `array/iterator.rs` and `array/push_pop.rs`: `js_array_spread_append`
  and the generic spread-push take the destination from `across_mut`
  around the iterator materialization instead of reading it afterwards.
- `object/wide_object_membership_tests.rs`: every probe re-reads the
  rooted receiver. The old shape bound `object.get_raw_mut_ptr()` once
  and then called `key()` — which allocates a string — repeatedly against
  that stale address.

Debt is back to exactly the recorded 945 with every module inside its
ceiling, so neither ratchet file needs an edit.

The string payload-access baseline moves the other way: #10070's rewrite
of `own_key_present` removed one open-coded
`size_of::<StringHeader>()` offset in `object_ops/keys_array.rs`, and
that inventory requires recorded progress. One line, 352 -> 351.

Claude-Session: https://claude.ai/code/session_017grKysEP6NBPpCiTSBjSZR
proggeramlug pushed a commit that referenced this pull request Sep 12, 2026
#10077 gives a dense array a queue front offset: `capacity` counts the slots
remaining AFTER the front, so logical element zero is no longer the end of
`ArrayHeader`. That PR converted every open-coded
`header + size_of::<ArrayHeader>()` element base in its own tree — but two
places on current `main` postdate its branch point and were never converted:

- `json_tape/cached_read.rs` (from #10064, landed in train161) open-codes the
  base on the hot materialized-array read. A materialized JSON array is an
  ordinary `GC_TYPE_ARRAY` that user code can `shift()`, so after this train
  that read would return the wrong element. Routed through
  `crate::array::array_elements_ptr`.
- `array/sort.rs` gained four more open-coded bases with the
  `publish_sorted_values` / `apply_sorted_indices` refactor. Converted with the
  conflict resolution in the pick itself; only the rustfmt reflow lands here.

Also converts the six raw-handle debt sites #10075's two new test modules
introduced. `--no-raise-vs <merge-base>` refuses both a ceiling on a module that
was absent at the base (`string/slice_tests.rs`) and a per-module raise
(`gc/tests/runtime_roots/string_slice.rs`, 1 -> 3), so the sites are converted
rather than recorded:

- `gc/tests/runtime_roots/string_slice.rs`: the two post-collection re-reads now
  run the collection inside `across_mut` / `across_const`, and the kept-slice
  assertions inside `with_const_ptr`. That also retires the module's one
  pre-existing site, so its ceiling line is DELETED — the deletion is the
  receipt — and the recorded total falls 945 -> 944.
- `string/slice_tests.rs`: the three argument-position reads become
  `with_const_ptr`, which is the documented shape for a self-rooting entry
  point such as `js_string_slice`.
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