Skip to content

Commit b2f9fb9

Browse files
authored
pythongh-140358: Bring back elapsed time and unreachable count to gc debug output (python#140359)
1 parent e09837f commit b2f9fb9

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

Lib/test/test_gc.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,32 @@ def __del__(self):
801801
rc, out, err = assert_python_ok('-c', code)
802802
self.assertEqual(out.strip(), b'__del__ called')
803803

804+
@unittest.skipIf(Py_GIL_DISABLED, "requires GC generations or increments")
805+
def test_gc_debug_stats(self):
806+
# Checks that debug information is printed to stderr
807+
# when DEBUG_STATS is set.
808+
code = """if 1:
809+
import gc
810+
gc.set_debug(%s)
811+
gc.collect()
812+
"""
813+
_, _, err = assert_python_ok("-c", code % "gc.DEBUG_STATS")
814+
self.assertRegex(err, b"gc: collecting generation [0-9]+")
815+
self.assertRegex(
816+
err,
817+
b"gc: objects in each generation: [0-9]+ [0-9]+ [0-9]+",
818+
)
819+
self.assertRegex(
820+
err, b"gc: objects in permanent generation: [0-9]+"
821+
)
822+
self.assertRegex(
823+
err,
824+
b"gc: done, .* unreachable, .* uncollectable, .* elapsed",
825+
)
826+
827+
_, _, err = assert_python_ok("-c", code % "0")
828+
self.assertNotIn(b"elapsed", err)
829+
804830
def test_global_del_SystemExit(self):
805831
code = """if 1:
806832
class ClassWithDel:
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Restore elapsed time and unreachable object count in GC debug output. These
2+
were inadvertently removed during a refactor of ``gc.c``. The debug log now
3+
again reports elapsed collection time and the number of unreachable objects.
4+
Contributed by Pål Grønås Drange.

Python/gc.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,8 +2077,10 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
20772077
if (reason != _Py_GC_REASON_SHUTDOWN) {
20782078
invoke_gc_callback(gcstate, "start", generation, &stats);
20792079
}
2080+
PyTime_t t1;
20802081
if (gcstate->debug & _PyGC_DEBUG_STATS) {
20812082
PySys_WriteStderr("gc: collecting generation %d...\n", generation);
2083+
(void)PyTime_PerfCounterRaw(&t1);
20822084
show_stats_each_generations(gcstate);
20832085
}
20842086
if (PyDTrace_GC_START_ENABLED()) {
@@ -2115,6 +2117,17 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
21152117
#endif
21162118
validate_spaces(gcstate);
21172119
_Py_atomic_store_int(&gcstate->collecting, 0);
2120+
2121+
if (gcstate->debug & _PyGC_DEBUG_STATS) {
2122+
PyTime_t t2;
2123+
(void)PyTime_PerfCounterRaw(&t2);
2124+
double d = PyTime_AsSecondsDouble(t2 - t1);
2125+
PySys_WriteStderr(
2126+
"gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n",
2127+
stats.collected + stats.uncollectable, stats.uncollectable, d
2128+
);
2129+
}
2130+
21182131
return stats.uncollectable + stats.collected;
21192132
}
21202133

0 commit comments

Comments
 (0)