Skip to content

Commit 934dc3b

Browse files
committed
gh-159437: Count garbage while clearing weakrefs
1 parent 4a2dcac commit 934dc3b

2 files changed

Lines changed: 13 additions & 6 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Count collectable objects while clearing weak references, avoiding a separate pass during garbage collection.

‎Python/gc.c‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -967,21 +967,26 @@ invoke_weakref_callbacks(PyGC_Head *wrcb_to_call, PyGC_Head *old)
967967
return num_freed;
968968
}
969969

970-
/* Clear all weakrefs to unreachable objects. When this returns, no object in
971-
* `unreachable` is weakly referenced anymore. See the comments above
972-
* prepare_callbacks() for why these weakrefs need to be cleared.
970+
/* Clear all weakrefs to unreachable objects without invoking callbacks.
971+
* When this returns, no object in `unreachable` is weakly referenced anymore.
972+
* See the comments above prepare_callbacks() for why these weakrefs need to be cleared.
973+
*
974+
* `unreachable`: Final collectable list; membership is unchanged.
975+
* Return: Number of objects in `unreachable`.
973976
*/
974-
static void
977+
static Py_ssize_t
975978
clear_weakrefs(PyGC_Head *unreachable)
976979
{
977980
PyGC_Head *gc;
978981
PyGC_Head *next;
982+
Py_ssize_t count = 0;
979983

980984
for (gc = GC_NEXT(unreachable); gc != unreachable; gc = next) {
981985
PyWeakReference **wrlist;
982986

983987
PyObject *op = FROM_GC(gc);
984988
next = GC_NEXT(gc);
989+
count++;
985990

986991
if (PyWeakref_Check(op)) {
987992
/* A weakref inside the unreachable set is always cleared. See
@@ -1015,6 +1020,8 @@ clear_weakrefs(PyGC_Head *unreachable)
10151020
_PyObject_ASSERT((PyObject *)wr, wr->wr_object == Py_None);
10161021
}
10171022
}
1023+
1024+
return count;
10181025
}
10191026

10201027
static void
@@ -1645,13 +1652,12 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
16451652
* and create new weakrefs. If those weakrefs were not cleared, they
16461653
* could reveal unreachable objects. Callbacks are not executed.
16471654
*/
1648-
clear_weakrefs(collectable);
1655+
stats.collected += clear_weakrefs(collectable);
16491656

16501657
/* Call tp_clear on objects in the collectable set. This will cause
16511658
* the reference cycles to be broken. It may also cause some objects
16521659
* in finalizers to be freed.
16531660
*/
1654-
stats.collected += gc_list_size(collectable);
16551661
delete_garbage(tstate, gcstate, collectable, old);
16561662

16571663
/* Collect statistics on uncollectable objects found and print

0 commit comments

Comments
 (0)