@@ -1363,6 +1363,7 @@ gc_list_set_space(PyGC_Head *list, int space)
13631363static void
13641364add_stats (GCState * gcstate , int gen , struct gc_collection_stats * stats )
13651365{
1366+ gcstate -> generation_stats [gen ].duration += stats -> duration ;
13661367 gcstate -> generation_stats [gen ].collected += stats -> collected ;
13671368 gcstate -> generation_stats [gen ].uncollectable += stats -> uncollectable ;
13681369 gcstate -> generation_stats [gen ].collections += 1 ;
@@ -1387,7 +1388,6 @@ gc_collect_young(PyThreadState *tstate,
13871388 validate_spaces (gcstate );
13881389 gcstate -> young .count = 0 ;
13891390 gcstate -> old [gcstate -> visited_space ].count ++ ;
1390- add_stats (gcstate , 0 , stats );
13911391 validate_spaces (gcstate );
13921392}
13931393
@@ -1701,7 +1701,6 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
17011701 assert (gc_list_is_empty (& increment ));
17021702 gcstate -> work_to_do -= increment_size ;
17031703
1704- add_stats (gcstate , 1 , stats );
17051704 if (gc_list_is_empty (not_visited )) {
17061705 completed_scavenge (gcstate );
17071706 }
@@ -1736,7 +1735,6 @@ gc_collect_full(PyThreadState *tstate,
17361735 completed_scavenge (gcstate );
17371736 _PyGC_ClearAllFreeLists (tstate -> interp );
17381737 validate_spaces (gcstate );
1739- add_stats (gcstate , 2 , stats );
17401738}
17411739
17421740/* This is the main function. Read this to understand how the
@@ -1846,10 +1844,11 @@ do_gc_callback(GCState *gcstate, const char *phase,
18461844 assert (PyList_CheckExact (gcstate -> callbacks ));
18471845 PyObject * info = NULL ;
18481846 if (PyList_GET_SIZE (gcstate -> callbacks ) != 0 ) {
1849- info = Py_BuildValue ("{sisnsn }" ,
1847+ info = Py_BuildValue ("{sisnsnsd }" ,
18501848 "generation" , generation ,
18511849 "collected" , stats -> collected ,
1852- "uncollectable" , stats -> uncollectable );
1850+ "uncollectable" , stats -> uncollectable ,
1851+ "duration" , stats -> duration );
18531852 if (info == NULL ) {
18541853 PyErr_FormatUnraisable ("Exception ignored while invoking gc callbacks" );
18551854 return ;
@@ -2080,15 +2079,15 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
20802079 if (reason != _Py_GC_REASON_SHUTDOWN ) {
20812080 invoke_gc_callback (gcstate , "start" , generation , & stats );
20822081 }
2083- PyTime_t t1 ;
20842082 if (gcstate -> debug & _PyGC_DEBUG_STATS ) {
20852083 PySys_WriteStderr ("gc: collecting generation %d...\n" , generation );
2086- (void )PyTime_PerfCounterRaw (& t1 );
20872084 show_stats_each_generations (gcstate );
20882085 }
20892086 if (PyDTrace_GC_START_ENABLED ()) {
20902087 PyDTrace_GC_START (generation );
20912088 }
2089+ PyTime_t start , stop ;
2090+ (void )PyTime_PerfCounterRaw (& start );
20922091 PyObject * exc = _PyErr_GetRaisedException (tstate );
20932092 switch (generation ) {
20942093 case 0 :
@@ -2103,6 +2102,9 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
21032102 default :
21042103 Py_UNREACHABLE ();
21052104 }
2105+ (void )PyTime_PerfCounterRaw (& stop );
2106+ stats .duration = PyTime_AsSecondsDouble (stop - start );
2107+ add_stats (gcstate , generation , & stats );
21062108 if (PyDTrace_GC_DONE_ENABLED ()) {
21072109 PyDTrace_GC_DONE (stats .uncollectable + stats .collected );
21082110 }
@@ -2124,12 +2126,9 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
21242126 _Py_atomic_store_int (& gcstate -> collecting , 0 );
21252127
21262128 if (gcstate -> debug & _PyGC_DEBUG_STATS ) {
2127- PyTime_t t2 ;
2128- (void )PyTime_PerfCounterRaw (& t2 );
2129- double d = PyTime_AsSecondsDouble (t2 - t1 );
21302129 PySys_WriteStderr (
21312130 "gc: done, %zd unreachable, %zd uncollectable, %.4fs elapsed\n" ,
2132- stats .collected + stats .uncollectable , stats .uncollectable , d
2131+ stats .collected + stats .uncollectable , stats .uncollectable , stats . duration
21332132 );
21342133 }
21352134
0 commit comments