@@ -181,7 +181,6 @@ _PyGC_Init(PyInterpreterState *interp)
181181 if (gcstate -> callbacks == NULL ) {
182182 return _PyStatus_NO_MEMORY ();
183183 }
184- gcstate -> heap_size = 0 ;
185184
186185 return _PyStatus_OK ();
187186}
@@ -1232,7 +1231,7 @@ gc_collect_region(PyThreadState *tstate,
12321231 struct gc_collection_stats * stats );
12331232
12341233static inline Py_ssize_t
1235- gc_list_set_space (PyGC_Head * list , int space )
1234+ gc_list_set_space (PyGC_Head * list , uintptr_t space )
12361235{
12371236 Py_ssize_t size = 0 ;
12381237 PyGC_Head * gc ;
@@ -1258,9 +1257,9 @@ gc_list_set_space(PyGC_Head *list, int space)
12581257 * N == 1.4 (1 + 4/threshold)
12591258 */
12601259
1261- /* Divide by 10, so that the default incremental threshold of 10
1262- * scans objects at 1% of the heap size */
1263- #define SCAN_RATE_DIVISOR 10
1260+ /* Multiply by 4 so that the default incremental threshold of 10
1261+ * scans objects at 20% the rate of object creation */
1262+ #define SCAN_RATE_MULTIPLIER 2
12641263
12651264static void
12661265add_stats (GCState * gcstate , int gen , struct gc_collection_stats * stats )
@@ -1312,7 +1311,7 @@ gc_collect_young(PyThreadState *tstate,
13121311 if (scale_factor < 1 ) {
13131312 scale_factor = 1 ;
13141313 }
1315- gcstate -> work_to_do += gcstate -> heap_size / SCAN_RATE_DIVISOR / scale_factor ;
1314+ gcstate -> work_to_do += survivor_count + survivor_count * SCAN_RATE_MULTIPLIER / scale_factor ;
13161315 add_stats (gcstate , 0 , stats );
13171316}
13181317
@@ -1383,12 +1382,12 @@ expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCStat
13831382static void
13841383completed_cycle (GCState * gcstate )
13851384{
1386- #ifdef Py_DEBUG
13871385 PyGC_Head * not_visited = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
13881386 assert (gc_list_is_empty (not_visited ));
1389- #endif
13901387 gcstate -> visited_space = flip_old_space (gcstate -> visited_space );
1391- gcstate -> work_to_do = 0 ;
1388+ if (gcstate -> work_to_do > 0 ) {
1389+ gcstate -> work_to_do = 0 ;
1390+ }
13921391}
13931392
13941393static void
@@ -1403,13 +1402,13 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14031402 if (scale_factor < 1 ) {
14041403 scale_factor = 1 ;
14051404 }
1405+ Py_ssize_t increment_size = 0 ;
14061406 gc_list_merge (& gcstate -> young .head , & increment );
14071407 gcstate -> young .count = 0 ;
14081408 if (gcstate -> visited_space ) {
14091409 /* objects in visited space have bit set, so we set it here */
14101410 gc_list_set_space (& increment , 1 );
14111411 }
1412- Py_ssize_t increment_size = 0 ;
14131412 while (increment_size < gcstate -> work_to_do ) {
14141413 if (gc_list_is_empty (not_visited )) {
14151414 break ;
@@ -1423,11 +1422,14 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14231422 PyGC_Head survivors ;
14241423 gc_list_init (& survivors );
14251424 gc_collect_region (tstate , & increment , & survivors , UNTRACK_TUPLES , stats );
1425+ Py_ssize_t survivor_count = gc_list_size (& survivors );
14261426 gc_list_merge (& survivors , visited );
14271427 assert (gc_list_is_empty (& increment ));
1428- gcstate -> work_to_do += gcstate -> heap_size / SCAN_RATE_DIVISOR / scale_factor ;
1428+ gcstate -> work_to_do += survivor_count + survivor_count * SCAN_RATE_MULTIPLIER / scale_factor ;
14291429 gcstate -> work_to_do -= increment_size ;
1430-
1430+ if (gcstate -> work_to_do < 0 ) {
1431+ gcstate -> work_to_do = 0 ;
1432+ }
14311433 validate_old (gcstate );
14321434 add_stats (gcstate , 1 , stats );
14331435 if (gc_list_is_empty (not_visited )) {
@@ -1673,7 +1675,7 @@ _PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs)
16731675}
16741676
16751677PyObject *
1676- _PyGC_GetObjects (PyInterpreterState * interp , int generation )
1678+ _PyGC_GetObjects (PyInterpreterState * interp , Py_ssize_t generation )
16771679{
16781680 assert (generation >= -1 && generation < NUM_GENERATIONS );
16791681 GCState * gcstate = & interp -> gc ;
@@ -1992,7 +1994,6 @@ _PyObject_GC_Link(PyObject *op)
19921994 gc -> _gc_next = 0 ;
19931995 gc -> _gc_prev = 0 ;
19941996 gcstate -> young .count ++ ; /* number of allocated GC objects */
1995- gcstate -> heap_size ++ ;
19961997 if (gcstate -> young .count > gcstate -> young .threshold &&
19971998 gcstate -> enabled &&
19981999 gcstate -> young .threshold &&
@@ -2119,7 +2120,6 @@ PyObject_GC_Del(void *op)
21192120 if (gcstate -> young .count > 0 ) {
21202121 gcstate -> young .count -- ;
21212122 }
2122- gcstate -> heap_size -- ;
21232123 PyObject_Free (((char * )op )- presize );
21242124}
21252125
0 commit comments