Skip to content

Conversation

markshannon
Copy link
Member

@markshannon markshannon commented Oct 17, 2025

This PR:

  • Counts number of actually tracked objects, instead of trackable objects. This ensures that untracking tuples has the desired effect of reducing GC overhead
  • Does not track most untrackable tuples during creation. This prevents large numbers of small tuples causing excessive GCs.

For the example in the original report this makes performance on main a bit better than 3.13.

Benchmarking results show this is about neutral on performance otherwise.

* Count number of actually tracked objects, instead of trackable objects. This ensures that untracking tuples has the desired effect of reducing GC overhead
* Do not track most untrackable tuples during creation. This prevents large numbers of small tuples causing execessive GCs.

/* Fast, but conservative check if an object maybe tracked
May return true for an object that is not tracked,
Will alwys return true for an object that is tracked.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Will alwys return true for an object that is tracked.
Will always return true for an object that is tracked.

if (gcstate->young.count > gcstate->young.threshold &&
gcstate->enabled &&
gcstate->young.threshold &&
if (gcstate->enabled &&
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to check gcstate->young.threshold here too, because documentation states that setting gcstate->young.threshold to 0 disables GC.

Copy link
Member

Choose a reason for hiding this comment

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

IMO, we need test on this. I've created a separate PR to add it:
#140304

uintptr_t not_visited = 1 ^ gcstate->visited_space;
gc->_gc_next = ((uintptr_t)generation0) | not_visited;
generation0->_gc_prev = (uintptr_t)gc;
gcstate->young.count++; /* number of allocated GC objects */
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
gcstate->young.count++; /* number of allocated GC objects */
gcstate->young.count++; /* number of tracked GC objects */

if (gcstate->young.count > gcstate->young.threshold &&
gcstate->enabled &&
gcstate->young.threshold &&
if (gcstate->enabled &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (gcstate->enabled &&
if (gcstate->enabled &&
gcstate->young.threshold &&

if (gcstate->young.count > 0) {
gcstate->young.count--;
}
gcstate->heap_size--;
Copy link
Member

@efimov-mikhail efimov-mikhail Oct 18, 2025

Choose a reason for hiding this comment

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

Do we really want to change heap_size here? Or maybe it'll be better to rename this to something like all_count?

if (gcstate->work_to_do < 0) {
return;
}
untrack_tuples(&gcstate->young.head);
Copy link
Contributor

Choose a reason for hiding this comment

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

IIUC, assess_work_to_do set gc.young.count to zero and if in untrack_tuples we untrack some tuples we don't decrease counter in _PyObject_GC_UNTRACK. On my sight, it is not very correct, but this gives us some room to subsequent trackings.

I'm not sure we should address this in this PR, but I think I should say this.

@sergey-miryanov
Copy link
Contributor

I'm not sure I get what android (x86_64) fails.
I can propose two solutions:

  1. Change default value for work_to_do from -5000 to 0
  2. Or remove newly added condition
if (gcstate->work_to_do < 0) {
    return;
}

@mhsmith
Copy link
Member

mhsmith commented Oct 19, 2025

I'm not at all familiar with the garbage collector, but one of the ways that Android differs from the other platforms is that it runs all the test suite serially in a single process.

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

Labels

needs backport to 3.14 bugs and security fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants