@@ -1287,8 +1287,8 @@ gc_list_set_space(PyGC_Head *list, int space)
12871287 */
12881288
12891289/* Multiply by 5, so that the default incremental threshold of 10
1290- * scans objects at the same rate as the young generation */
1291- #define SCAN_RATE_MULTIPLIER 10
1290+ * scans objects at half the rate of the young generation */
1291+ #define SCAN_RATE_MULTIPLIER 5
12921292
12931293static void
12941294add_stats (GCState * gcstate , int gen , struct gc_collection_stats * stats )
@@ -1428,8 +1428,30 @@ completed_cycle(GCState *gcstate)
14281428 gc = next ;
14291429 }
14301430 gcstate -> work_to_do = 0 ;
1431+ gcstate -> scan_reachable = 1 ;
14311432}
14321433
1434+
1435+ static void
1436+ gc_mark_reachable (PyThreadState * tstate )
1437+ {
1438+ GCState * gcstate = & tstate -> interp -> gc ;
1439+ PyGC_Head * visited = & gcstate -> old [gcstate -> visited_space ].head ;
1440+ PyObject * sysdict = tstate -> interp -> sysdict ;
1441+ PyObject * sysmod = PyDict_GetItemString (sysdict , "modules" );
1442+ if (sysmod == NULL ) {
1443+ return ;
1444+ }
1445+ PyGC_Head reachable ;
1446+ gc_list_init (& reachable );
1447+ PyGC_Head * gc = _Py_AS_GC (sysmod );
1448+ gc_list_move (gc , & reachable );
1449+ gc_set_old_space (gc , gcstate -> visited_space );
1450+ gcstate -> work_to_do -= expand_region_transitively_reachable (& reachable , gc , gcstate );
1451+ gc_list_merge (& reachable , visited );
1452+ }
1453+
1454+
14331455static void
14341456gc_collect_increment (PyThreadState * tstate , struct gc_collection_stats * stats )
14351457{
@@ -1439,6 +1461,10 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14391461 PyGC_Head * visited = & gcstate -> old [gcstate -> visited_space ].head ;
14401462 PyGC_Head increment ;
14411463 gc_list_init (& increment );
1464+ if (gcstate -> scan_reachable ) {
1465+ gc_mark_reachable (tstate );
1466+ gcstate -> scan_reachable = 0 ;
1467+ }
14421468 Py_ssize_t scale_factor = gcstate -> old [0 ].threshold ;
14431469 if (scale_factor < 1 ) {
14441470 scale_factor = 1 ;
@@ -1461,7 +1487,7 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14611487 gc_list_validate_space (& survivors , gcstate -> visited_space );
14621488 gc_list_merge (& survivors , visited );
14631489 assert (gc_list_is_empty (& increment ));
1464- Py_ssize_t delta = (gcstate -> heap_size - gcstate -> prior_heap_size )* 2 ;
1490+ Py_ssize_t delta = (gcstate -> heap_size - gcstate -> prior_heap_size )* 3 ;
14651491 delta += gcstate -> young .threshold * SCAN_RATE_MULTIPLIER / scale_factor ;
14661492 if (delta > 0 ) {
14671493 gcstate -> work_to_do += delta ;
0 commit comments