Skip to content

Commit c1bfd4c

Browse files
miss-islingtonpgdr
andauthored
[3.14] gh-140358: Bring back elapsed time and unreachable count to gc debug output (GH-140359) (#140405)
Co-authored-by: Pål Grønås Drange <[email protected]>
1 parent ce1deb9 commit c1bfd4c

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
@@ -776,6 +776,32 @@ def __del__(self):
776776
rc, out, err = assert_python_ok('-c', code)
777777
self.assertEqual(out.strip(), b'__del__ called')
778778

779+
@unittest.skipIf(Py_GIL_DISABLED, "requires GC generations or increments")
780+
def test_gc_debug_stats(self):
781+
# Checks that debug information is printed to stderr
782+
# when DEBUG_STATS is set.
783+
code = """if 1:
784+
import gc
785+
gc.set_debug(%s)
786+
gc.collect()
787+
"""
788+
_, _, err = assert_python_ok("-c", code % "gc.DEBUG_STATS")
789+
self.assertRegex(err, b"gc: collecting generation [0-9]+")
790+
self.assertRegex(
791+
err,
792+
b"gc: objects in each generation: [0-9]+ [0-9]+ [0-9]+",
793+
)
794+
self.assertRegex(
795+
err, b"gc: objects in permanent generation: [0-9]+"
796+
)
797+
self.assertRegex(
798+
err,
799+
b"gc: done, .* unreachable, .* uncollectable, .* elapsed",
800+
)
801+
802+
_, _, err = assert_python_ok("-c", code % "0")
803+
self.assertNotIn(b"elapsed", err)
804+
779805
def test_global_del_SystemExit(self):
780806
code = """if 1:
781807
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
@@ -2024,8 +2024,10 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
20242024
if (reason != _Py_GC_REASON_SHUTDOWN) {
20252025
invoke_gc_callback(gcstate, "start", generation, &stats);
20262026
}
2027+
PyTime_t t1;
20272028
if (gcstate->debug & _PyGC_DEBUG_STATS) {
20282029
PySys_WriteStderr("gc: collecting generation %d...\n", generation);
2030+
(void)PyTime_PerfCounterRaw(&t1);
20292031
show_stats_each_generations(gcstate);
20302032
}
20312033
if (PyDTrace_GC_START_ENABLED()) {
@@ -2062,6 +2064,17 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
20622064
#endif
20632065
validate_spaces(gcstate);
20642066
_Py_atomic_store_int(&gcstate->collecting, 0);
2067+
2068+
if (gcstate->debug & _PyGC_DEBUG_STATS) {
2069+
PyTime_t t2;
2070+
(void)PyTime_PerfCounterRaw(&t2);
2071+
double d = PyTime_AsSecondsDouble(t2 - t1);
2072+
PySys_WriteStderr(
2073+
"gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n",
2074+
stats.collected + stats.uncollectable, stats.uncollectable, d
2075+
);
2076+
}
2077+
20652078
return stats.uncollectable + stats.collected;
20662079
}
20672080

0 commit comments

Comments
 (0)