-
-
Notifications
You must be signed in to change notification settings - Fork 161
perf(gc): young-entry logs for the side-table root scanners #9755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
ca2d1c5
perf(gc): young-entry logs for the side-table root scanners
7d3c955
style(gc): rustfmt and split the four files this change pushed past t…
b1c5523
fix(gc): make rule 1 enforceable — the young-log tests could not fail
2922731
test(gc): cover the four `shapes.indices` arm sites the audit found u…
ceabd7e
perf(gc): recycle the young logs' buffers instead of regrowing them e…
b775dfb
fix(gc): arm the young log from `family_append_fresh` too
47b042c
perf(gc): drop the shape-cache young log — it skipped 0 % and cost 35…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| ### Performance | ||
|
|
||
| - **Minor collections no longer walk every runtime side table.** A copying | ||
| minor's three root-scan passes — and a budgeted minor's initial root scan | ||
| and final remark — visited every entry of the closure dynamic-prop tables, | ||
| the string-keyed descriptor tables, the shape family/slot-index maps and | ||
| the transition cache on every collection, to discover that nothing in them | ||
| pointed at the nursery. On the compiled claude-code TUI | ||
| that was ~35k shape families, ~120k descriptors and ~13k closure owners | ||
| per walk, 41 minors per streamed reply, all reporting `slots=0`: 34–56 ms | ||
| of scanner time per minor. | ||
|
|
||
| Each of those tables now keeps a **young-entry log** | ||
| (`crates/perry-runtime/src/gc/young_log.rs`): the keys of entries that may | ||
| hold a pointer a minor can act on (nursery, longlived or malloc-GC — an old | ||
| object is neither moved nor swept by any minor, and never becomes young | ||
| again). Writers note the key before publishing the entry; a minor-scoped | ||
| scanner (`RuntimeRootVisitor::young_scope`) visits only the logged keys, | ||
| with the same per-entry body as the full walk, and re-logs an entry iff it | ||
| is still relevant afterwards; a full trace walks everything and rebuilds | ||
| the log. The copied-minor and fallback-minor dead-owner prunes of the same | ||
| tables iterate the log as well. Under `debug_assertions` every minor-scoped | ||
| walk first re-derives the relevant set from the authoritative table and | ||
| panics on a key the log does not name, so a writer that forgets to note is | ||
| a red test rather than a silently collected object. `PERRY_GC_DIAG=1` | ||
| prints `[gc-young-log]` rows (logged / visited / kept / table size) per | ||
| table and cycle. | ||
|
|
||
| The **shape cache** was measured and deliberately left on its plain walk. | ||
| Its canonical keys arrays are allocated in the longlived arena, which | ||
| `addr_is_minor_relevant` must answer `true` for, so no entry ever leaves a | ||
| log there: on the claude-code TUI the log named 100 % of the table in every | ||
| one of 107 collections (0 % skipped) and cost **35 % more** than the walk it | ||
| replaced. The four tables above skip 75–93 %. | ||
|
|
||
| - **The post-minor remembered-set coverage restore is proportional to what | ||
| the dirty scan could not cover.** `restore_surviving_dirty_coverage` | ||
| (#5029) re-walked every slot of every object on the pre-cycle dirty pages | ||
| after each copying minor. The minor's own dirty scan already re-remembers | ||
| each slot it visits with the same predicate, so objects it visited | ||
| completely (every pointer slot on a dirty page and inside the body) are | ||
| now skipped; multi-page arrays and owners of out-of-body buffers are still | ||
| walked. Debug builds walk the skipped objects too and panic if the walk | ||
| would have added a page. `[gc-restore-coverage]` reports objects | ||
| walked/skipped and pages added. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use
RUST_TEST_THREADS=1in the documented command.perry-runtimetests are not parallel-safe. The command currently uses-- --test-threads=1, but the repository rule requiresRUST_TEST_THREADS=1.Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents
Source: Coding guidelines