GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-159137: Keep surviving objects in order in the garbage collector by pablogsal · Pull Request #159152 · python/cpython

Conversation

@pablogsal

@pablogsal pablogsal commented Oct 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

move_unreachable() moves objects with zero gc_refs out of the generation and appends them back when they turn out to be reachable. That leaves the survivors in the order the collector reached them, so every later walk of the generation misses the cache at each step. This flags those objects in place and traverses the reachable ones from a small stack, so the generation keeps its allocation order.

Benchmarks

GC time from gc.get_stats(). Medians of four runs per executable (nine for the AST heap), in baseline/candidate/candidate/baseline order.

Workload GC before GC after Less GC time
Sphinx building the CPython docs 28.902 s 21.684 s 25.0%
Pylint on five stdlib packages 2.516 s 1.979 s 21.3%
Parso parsing the standard library 1.674 s 0.657 s 60.8%
sqlglot parsing and transpiling 4,000 queries 4.762 s 3.690 s 22.5%
Beautiful Soup parsing 90 HTML pages 2.443 s 1.764 s 27.8%
Black checking three stdlib packages 1.098 s 1.019 s 7.3%
Full collection of 720,000 live AST objects 292.4 ms 113.0 ms 61.3%
Geometric mean 35.5%

Collector cycles on the Pylint run. Width is the share before the change, blue frames take fewer cycles after it:

pylint

  • Issue: Speed up garbage collector #159137

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@pablogsal
pythongh-159137: Keep surviving objects in order in the garbage colle…
d7de116
…ctor
@bedevere-app bedevere-app Bot mentioned this pull request Oct 10, 2026
Speed up garbage collector #159137
Open
@pablogsal pablogsal added the DO-NOT-MERGE label Oct 10, 2026
pablogsal added 4 commits October 10, 2026 22:49
@pablogsal
Drop the NEWS entry and the doc changes
3a73e71
@pablogsal
Simplify
51dc0ca
@pablogsal
Update the internal docs
40e9364
@pablogsal
Move runs of unreachable objects at once
514d0f4
@pablogsal
pablogsal requested review from nascheme and sergey-miryanov October 10, 2026 22:46
@pablogsal pablogsal removed the DO-NOT-MERGE label Oct 10, 2026
@pablogsal
pablogsal marked this pull request as ready for review October 10, 2026 22:47
@bedevere-app bedevere-app Bot added the awaiting core review label Oct 10, 2026
pablogsal added 2 commits October 10, 2026 23:54
@pablogsal
Add a NEWS entry
5618614
@pablogsal
Look for the unreachable objects from both ends of the list
6c08848
@pablogsal pablogsal mentioned this pull request Oct 11, 2026
gh-159137: Restore known-root marking for the GIL garbage collector #159162
Closed
sergey-miryanov
sergey-miryanov reviewed Oct 11, 2026
View reviewed changes
Comment thread Python/gc.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

@nascheme

nascheme commented Oct 11, 2026

Copy link
Copy Markdown
Member

LGTM. Some comments, not blockers for merging:

  • are we quite confident allocating reachable_state on the stack is okay (it's 8 KB)? When GC is called from the eval breaker, it's probably okay. What about calling gc.collect() explicitly? Perhaps we should just heap allocate this. If that fails, you could fallback to a zero size stack (or maybe a small C stack allocated one). If heap allocated, you could make it a bit larger than 1024 slots, assuming benchmarking justifies that.
  • for the two-ended sweep, a comment about why the backward step can't read an already spliced node would be good. The code is correct but it's suble.
  • gc.get_objects() generally returns them "in that order" but only if the stack is large enough. Should perhaps be careful about making it should like something that can be relied on.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

nascheme
nascheme approved these changes Oct 11, 2026
View reviewed changes
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting core review labels Oct 11, 2026
@pablogsal

pablogsal commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

Closing this PR. I’ve learned that @brandtbucher's mentee has been working on something very close to this for a while and was planning to open source it once a few things cleared up. Rather than duplicate that effort, I’d prefer to focus on their work and help get it upstream, so I’ll be following up on that instead :)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal pablogsal closed this Oct 12, 2026
This was referenced Oct 23, 2026
gh-159137: Reuse candidate pointers in the free-threaded GC mark phase #160462
Closed
gh-159137: Traverse dictionary values as spans in the free-threaded GC #160463
Closed
gh-159137: Skip unnecessary free-threaded GC finalizer and weakref scans #160464
Closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@sergey-miryanov sergey-miryanov sergey-miryanov left review comments
@nascheme nascheme nascheme approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

awaiting merge

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

3 participants

@pablogsal @nascheme @sergey-miryanov
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.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.