Skip to content

perf(runtime): typed-feedback store forwards when recording is off; one-entry cache for the external-slot remembered set (ECS round 4) - #8951

Merged
proggeramlug merged 2 commits into
PerryTS:mainfrom
proggeramlug:perf/ecs-r4-external-cache
Aug 28, 2026
Merged

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Two runtime mechanisms from the ECS round-4 chain, cut from current main. Suites on the isolated perrymaster gate: runtime (2752, incl. the new external-cache test). Paired measurement on the codehz/ecs "5k entities: 3 commands each + sync" row (idle Mac mini, alternating pairs) follows in a comment.

  • The typed-feedback array store forwards at once when recording is off. js_typed_feedback_array_set_index_or_string converted the index and made two out-of-line calls (observe_array, record_guard_pass) whose first statement is "recording is off, return" — 1.5% of the merged-main ECS frame on column[index] = record. One flag test (typed_feedback_enabled, the default is off), then the strict store; the recording path is unchanged when the env enables it.
  • A one-entry cache in front of the external-slot remembered set. A Map's entries buffer is an external slot span, so every map.set(k, v) on an old map reached mark_dirty_external_slot_page: a thread-local table probe plus a linear scan of that page's header list (which grows with every map whose buffer shares the page) — the two hottest offsets of js_map_set on merged main. The (page, header) pair is cached inline in HotTls, recorded only after the table holds it and dropped wherever the table drops a pair (clear_one_external_dirty_slot_header, which every clear path goes through), so a repeated store into the same map answers from two loads — the external-slot twin of the inline-slot dirty-page cache (perf: ECS round 4 — barrier early exits, inline captureless some loop, lean Map/Set lanes, empty-pop fast path, codegen-time const fold, inline hot-TLS values (−16.7%) #8916). external_dirty_slot_pair_cache_mirrors_the_table pins hit / miss / re-record-after-clear.

https://claude.ai/code/session_01FUvFrRNZyc5qknBiJbYbby

Summary by CodeRabbit

  • Performance

    • Improved garbage-collection tracking efficiency for repeated external-slot updates.
    • Streamlined array assignments when typed feedback is disabled by avoiding unnecessary processing.
  • Reliability

    • Ensured external-slot tracking remains consistent when remembered entries are cleared.
  • Tests

    • Added coverage for external-slot cache hits, misses, and reset behavior.
  • Documentation

    • Added changelog notes describing the runtime and garbage-collection improvements.

Ralph Küpper added 2 commits August 28, 2026 11:35
…ecording is off; a one-entry cache in front of the external-slot remembered set

js_typed_feedback_array_set_index_or_string converted the index and made two
out-of-line calls whose first statement is "recording is off, return" — 1.5%
of an ECS frame on `column[index] = record`. One flag test, then the strict
store.

A Map's entries buffer is an external slot span, so every map.set(k, v) on
an old map reached mark_dirty_external_slot_page: a thread-local table
probe plus a linear scan of the page's header list, which grows with every
map whose buffer shares the page. The (page, header) pair is now cached
inline in HotTls — recorded only after the table holds it, dropped wherever
the table drops a pair — so a repeated store into the same map answers from
two loads, exactly as the inline-slot dirty-page cache does.

Claude-Session: https://claude.ai/code/session_01FUvFrRNZyc5qknBiJbYbby
@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 76d5ca3b-ab2f-4980-916a-c58229bebcc1

📥 Commits

Reviewing files that changed from the base of the PR and between cae1b95 and 9bc29ae.

📒 Files selected for processing (6)
  • changelog.d/8951-external-slot-cache.md
  • crates/perry-runtime/src/gc/barrier/maintenance.rs
  • crates/perry-runtime/src/gc/barrier/mod.rs
  • crates/perry-runtime/src/gc/tests/barrier.rs
  • crates/perry-runtime/src/tls_hot.rs
  • crates/perry-runtime/src/typed_feedback.rs

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


📝 Walkthrough

Walkthrough

The runtime adds a direct strict-store path when typed feedback is disabled. It also adds a one-entry hot-TLS cache for repeated external dirty-slot pairs and invalidates the cache when entries are cleared.

Changes

Runtime optimizations

Layer / File(s) Summary
Direct typed-feedback array store path
crates/perry-runtime/src/typed_feedback.rs
Disabled typed feedback now performs the strict array store directly.
External dirty-slot pair cache
crates/perry-runtime/src/tls_hot.rs, crates/perry-runtime/src/gc/barrier/mod.rs, crates/perry-runtime/src/gc/barrier/maintenance.rs, crates/perry-runtime/src/gc/tests/barrier.rs, changelog.d/8951-external-slot-cache.md
HotTls stores the latest external dirty page and header. Marking checks this pair before probing the remembered-set table. Header removal clears the cache. Tests cover cache hits, misses, table lookups, and reset behavior.

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

Merge Risk: ⚪ Minimal · up to 9bc29

This PR makes localized runtime performance changes while preserving array-store behavior and remembered-set cache invalidation. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

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 8 functions across 5 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description explains the two changes and reports test coverage, but it does not use the required section headings or provide the required related-issue, test-plan checklist, and contributor checkl… Reformat the description using the repository template. Add Summary, Changes, Related issue with an issue reference or "n/a", Test plan with verification commands and completed checkboxes, Screenshots / output if applicable, and the require…
✅ Passed checks (3 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 both runtime optimizations and uses a concise, specific performance-oriented summary.
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 8 functions across 5 files. (1 skipped: 1 unsupported.)

Full details: Description check

Explanation

The description explains the two changes and reports test coverage, but it does not use the required section headings or provide the required related-issue, test-plan checklist, and contributor checklist information.

Resolution

Reformat the description using the repository template. Add Summary, Changes, Related issue with an issue reference or "n/a", Test plan with verification commands and completed checkboxes, Screenshots / output if applicable, and the required Checklist entries.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Gate on the isolated perrymaster clone for 9bc29aeb5 (base cae1b95c3): runtime suite 2752/2752 (incl. the new external_dirty_slot_pair_cache_mirrors_the_table), codegen lib 1334, native_proof_regressions 280, transform lib 119 — all green; lint gates and merge-base ratchets flat (576/967). Paired measurement on the mini queued (control = cae1b95c3).

@proggeramlug

Copy link
Copy Markdown
Contributor Author

Paired measurement (idle Mac mini, 9 alternating pairs, codehz/ecs "5k entities: 3 commands each + sync"): control = base cae1b95c3, candidate = this branch: 3.246 → 3.207 ms/op, +1.20%, 9/9 (r4n-screen.json, oracles 18/18). The Darwin barrier suite passes on the Mac too (74/74, incl. the new pair-cache test).

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