Skip to content

gh-159437: Skip unnecessary legacy finalizer scans - #159593

Draft
mfalco-oai wants to merge 5 commits into
python:mainfrom
mfalco-oai:mfalco-oai/gh-159437-gc-legacy-skip
Draft

mfalco-oai wants to merge 5 commits into
python:mainfrom
mfalco-oai:mfalco-oai/gh-159437-gc-legacy-skip

Conversation

@mfalco-oai

@mfalco-oai mfalco-oai commented Oct 16, 2026 •

Copy link
Copy Markdown

With this optimization the GIL collector counts mortal candidates whose type defines tp_del during the existing reference passes. A zero count rules out legacy finalizers in the garbage, so the collector skips their classification and reachability scans. On that path, it also clears unreachable tags during weakref preparation. With DEBUG_COLLECTABLE, the tags are cleared earlier, before debug output can run Python.

Count the stable unreachable set while preparing callbacks and retain a conservative cleanup flag. Reuse the count only when late weakref clearing has no work, and force fresh cleanup and counting after resurrection analysis.

Add a regression for a callback-free weakref observed when clearing a young cycle releases an older finalizer.
Count tp_del candidates during the existing reference traversals so zero can skip legacy classification. Reuse callback preparation to clear initial unreachable tags, while preserving normalized links before DEBUG_COLLECTABLE output can invoke Python.

Cover debug visibility of weakrefs with callbacks and legacy classification during a generation 0 collection.
@python-cla-bot

python-cla-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

@bedevere-app bedevere-app Bot added the type-feature A feature request or enhancement label Oct 16, 2026
Comment thread Python/gc.c
PyObject *op = FROM_GC(gc);
traverse = Py_TYPE(op)->tp_traverse;
PyTypeObject *type = Py_TYPE(op);
legacy_finalizer_count += type->tp_del != NULL;

@pablogsal pablogsal Oct 17, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This checks tp_del on every mortal candidate to avoid scanning the objects that end up as garbage. Even a live object with tp_del prevents the skip.

The reachability walk seems a better place to gather this. In a related change I made in an earlier PR, survivor counting was folded into that walk. We could use the same placement here and set a boolean when an object enters the provisional garbage list. If it gets rescued later, we just do the scan unnecessarily.

That removes this bookkeeping from the reference walkers. The exact count is unneeded anyway since we only need to know whether any legacy finalizers are present. This alternative still needs building and measuring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type-feature A feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants