Skip to content

Commit 8153914

Browse files
naschemesergey-miryanov
authored andcommitted
Add notes about untrack_dicts() change.
1 parent b50da36 commit 8153914

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

InternalDocs/garbage_collector.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,14 @@ tuples can be untracked. A tuple can be untracked if all of its contents are
692692
already not tracked. Tuples are examined for untracking in all garbage collection
693693
cycles.
694694

695+
Dictionaries are always tracked from creation and are not untracked by the
696+
garbage collector. Earlier versions (up to 3.13) used lazy tracking: empty or
697+
atomic-only dicts were untracked on creation and re-tracked when a trackable
698+
value was inserted (via `MAINTAIN_TRACKING`), and full collections called
699+
`_PyDict_MaybeUntrack` to prune dicts whose values had become atomic. That
700+
machinery was removed in 3.14 (GH-127010) because the per-set-item cost of
701+
checking the tracking invariant outweighed the savings on full collections.
702+
695703
The garbage collector module provides the Python function `is_tracked(obj)`, which returns
696704
the current tracking status of the object. Subsequent garbage collections may change the
697705
tracking status of the object.

Python/gc.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,10 +1402,13 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
14021402
gc_list_merge(young, old);
14031403
}
14041404
else {
1405-
/* We only un-track dicts in full collections, to avoid quadratic
1406-
dict build-up. See issue #14775.
1407-
Note: _PyDict_MaybeUntrack was removed in 3.14, so dict
1408-
untracking during GC is no longer done. */
1405+
// In Python <= 3.13, we called untrack_dicts(young) here to untrack
1406+
// atomic-only dicts (see issue #14775). Python 3.14 removed the lazy
1407+
// dict tracking machinery entirely (GH-127010) -- dicts are always
1408+
// tracked from creation and never untracked by GC. That way, we don't
1409+
// have to restore MAINTAIN_TRACKING across every PyDict_SetItem call
1410+
// site; the cost is slightly more work for full collections on dicts
1411+
// with only atomic values.
14091412
gcstate->long_lived_pending = 0;
14101413
gcstate->long_lived_total = gc_list_size(young);
14111414
}

0 commit comments

Comments
 (0)