Skip to content

Commit 739c7da

Browse files
Add collection time to gc callbacks
1 parent f0291c3 commit 739c7da

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

Python/gc.c

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,18 +1838,32 @@ gc_collect_region(PyThreadState *tstate,
18381838
*/
18391839
static void
18401840
do_gc_callback(GCState *gcstate, const char *phase,
1841-
int generation, struct gc_collection_stats *stats)
1841+
int generation, struct gc_collection_stats *stats,
1842+
PyTime_t *t1, PyTime_t *t2)
18421843
{
18431844
assert(!PyErr_Occurred());
18441845

18451846
/* The local variable cannot be rebound, check it for sanity */
18461847
assert(PyList_CheckExact(gcstate->callbacks));
18471848
PyObject *info = NULL;
18481849
if (PyList_GET_SIZE(gcstate->callbacks) != 0) {
1849-
info = Py_BuildValue("{sisnsn}",
1850-
"generation", generation,
1851-
"collected", stats->collected,
1852-
"uncollectable", stats->uncollectable);
1850+
PyTime_t dt = 0;
1851+
if (t1 && t2 && *t1 > 0 && *t2 > 0) {
1852+
dt = *t2 - *t1;
1853+
}
1854+
if (dt > 0) {
1855+
info = Py_BuildValue("{sisnsnsd}",
1856+
"generation", generation,
1857+
"collected", stats->collected,
1858+
"uncollectable", stats->uncollectable,
1859+
"collection_time", PyTime_AsSecondsDouble(dt));
1860+
}
1861+
else {
1862+
info = Py_BuildValue("{sisnsn}",
1863+
"generation", generation,
1864+
"collected", stats->collected,
1865+
"uncollectable", stats->uncollectable);
1866+
}
18531867
if (info == NULL) {
18541868
PyErr_FormatUnraisable("Exception ignored while invoking gc callbacks");
18551869
return;
@@ -1884,12 +1898,13 @@ do_gc_callback(GCState *gcstate, const char *phase,
18841898

18851899
static void
18861900
invoke_gc_callback(GCState *gcstate, const char *phase,
1887-
int generation, struct gc_collection_stats *stats)
1901+
int generation, struct gc_collection_stats *stats,
1902+
PyTime_t *t1, PyTime_t *t2)
18881903
{
18891904
if (gcstate->callbacks == NULL) {
18901905
return;
18911906
}
1892-
do_gc_callback(gcstate, phase, generation, stats);
1907+
do_gc_callback(gcstate, phase, generation, stats, t1, t2);
18931908
}
18941909

18951910
static int
@@ -2077,17 +2092,18 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
20772092

20782093
struct gc_collection_stats stats = { 0 };
20792094
if (reason != _Py_GC_REASON_SHUTDOWN) {
2080-
invoke_gc_callback(gcstate, "start", generation, &stats);
2095+
invoke_gc_callback(gcstate, "start", generation, &stats, NULL, NULL);
20812096
}
2082-
PyTime_t t1;
20832097
if (gcstate->debug & _PyGC_DEBUG_STATS) {
20842098
PySys_WriteStderr("gc: collecting generation %d...\n", generation);
2085-
(void)PyTime_PerfCounterRaw(&t1);
20862099
show_stats_each_generations(gcstate);
20872100
}
20882101
if (PyDTrace_GC_START_ENABLED()) {
20892102
PyDTrace_GC_START(generation);
20902103
}
2104+
PyTime_t t1 = {0};
2105+
(void)PyTime_PerfCounterRaw(&t1);
2106+
20912107
PyObject *exc = _PyErr_GetRaisedException(tstate);
20922108
switch(generation) {
20932109
case 0:
@@ -2102,11 +2118,14 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
21022118
default:
21032119
Py_UNREACHABLE();
21042120
}
2121+
PyTime_t t2 = {0};
2122+
(void)PyTime_PerfCounterRaw(&t2);
2123+
21052124
if (PyDTrace_GC_DONE_ENABLED()) {
21062125
PyDTrace_GC_DONE(stats.uncollectable + stats.collected);
21072126
}
21082127
if (reason != _Py_GC_REASON_SHUTDOWN) {
2109-
invoke_gc_callback(gcstate, "stop", generation, &stats);
2128+
invoke_gc_callback(gcstate, "stop", generation, &stats, &t1, &t2);
21102129
}
21112130
_PyErr_SetRaisedException(tstate, exc);
21122131
GC_STAT_ADD(generation, objects_collected, stats.collected);
@@ -2121,8 +2140,6 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
21212140
_Py_atomic_store_int(&gcstate->collecting, 0);
21222141

21232142
if (gcstate->debug & _PyGC_DEBUG_STATS) {
2124-
PyTime_t t2;
2125-
(void)PyTime_PerfCounterRaw(&t2);
21262143
double d = PyTime_AsSecondsDouble(t2 - t1);
21272144
PySys_WriteStderr(
21282145
"gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n",

0 commit comments

Comments
 (0)