@@ -182,6 +182,7 @@ _PyGC_Init(PyInterpreterState *interp)
182182 if (gcstate -> callbacks == NULL ) {
183183 return _PyStatus_NO_MEMORY ();
184184 }
185+ gcstate -> heap_size = 0 ;
185186
186187 return _PyStatus_OK ();
187188}
@@ -1232,7 +1233,7 @@ gc_collect_region(PyThreadState *tstate,
12321233 struct gc_collection_stats * stats );
12331234
12341235static inline Py_ssize_t
1235- gc_list_set_space (PyGC_Head * list , uintptr_t space )
1236+ gc_list_set_space (PyGC_Head * list , int space )
12361237{
12371238 Py_ssize_t size = 0 ;
12381239 PyGC_Head * gc ;
@@ -1258,9 +1259,9 @@ gc_list_set_space(PyGC_Head *list, uintptr_t space)
12581259 * N == 1.4 (1 + 4/threshold)
12591260 */
12601261
1261- /* Multiply by 4 so that the default incremental threshold of 10
1262- * scans objects at 20% the rate of object creation */
1263- #define SCAN_RATE_MULTIPLIER 2
1262+ /* Divide by 10, so that the default incremental threshold of 10
1263+ * scans objects at 1% of the heap size */
1264+ #define SCAN_RATE_DIVISOR 10
12641265
12651266static void
12661267add_stats (GCState * gcstate , int gen , struct gc_collection_stats * stats )
@@ -1313,7 +1314,7 @@ gc_collect_young(PyThreadState *tstate,
13131314 if (scale_factor < 1 ) {
13141315 scale_factor = 1 ;
13151316 }
1316- gcstate -> work_to_do += survivor_count + survivor_count * SCAN_RATE_MULTIPLIER / scale_factor ;
1317+ gcstate -> work_to_do += gcstate -> heap_size / SCAN_RATE_DIVISOR / scale_factor ;
13171318 add_stats (gcstate , 0 , stats );
13181319}
13191320
@@ -1384,12 +1385,12 @@ expand_region_transitively_reachable(PyGC_Head *container, PyGC_Head *gc, GCStat
13841385static void
13851386completed_cycle (GCState * gcstate )
13861387{
1388+ #ifdef Py_DEBUG
13871389 PyGC_Head * not_visited = & gcstate -> old [gcstate -> visited_space ^1 ].head ;
13881390 assert (gc_list_is_empty (not_visited ));
1391+ #endif
13891392 gcstate -> visited_space = flip_old_space (gcstate -> visited_space );
1390- if (gcstate -> work_to_do > 0 ) {
1391- gcstate -> work_to_do = 0 ;
1392- }
1393+ gcstate -> work_to_do = 0 ;
13931394}
13941395
13951396static void
@@ -1404,13 +1405,13 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14041405 if (scale_factor < 1 ) {
14051406 scale_factor = 1 ;
14061407 }
1407- Py_ssize_t increment_size = 0 ;
14081408 gc_list_merge (& gcstate -> young .head , & increment );
14091409 gcstate -> young .count = 0 ;
14101410 if (gcstate -> visited_space ) {
14111411 /* objects in visited space have bit set, so we set it here */
14121412 gc_list_set_space (& increment , 1 );
14131413 }
1414+ Py_ssize_t increment_size = 0 ;
14141415 while (increment_size < gcstate -> work_to_do ) {
14151416 if (gc_list_is_empty (not_visited )) {
14161417 break ;
@@ -1425,14 +1426,11 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14251426 PyGC_Head survivors ;
14261427 gc_list_init (& survivors );
14271428 gc_collect_region (tstate , & increment , & survivors , UNTRACK_TUPLES , stats );
1428- Py_ssize_t survivor_count = gc_list_size (& survivors );
14291429 gc_list_merge (& survivors , visited );
14301430 assert (gc_list_is_empty (& increment ));
1431- gcstate -> work_to_do += survivor_count + survivor_count * SCAN_RATE_MULTIPLIER / scale_factor ;
1431+ gcstate -> work_to_do += gcstate -> heap_size / SCAN_RATE_DIVISOR / scale_factor ;
14321432 gcstate -> work_to_do -= increment_size ;
1433- if (gcstate -> work_to_do < 0 ) {
1434- gcstate -> work_to_do = 0 ;
1435- }
1433+
14361434 validate_old (gcstate );
14371435 add_stats (gcstate , 1 , stats );
14381436 if (gc_list_is_empty (not_visited )) {
@@ -1678,7 +1676,7 @@ _PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs)
16781676}
16791677
16801678PyObject *
1681- _PyGC_GetObjects (PyInterpreterState * interp , Py_ssize_t generation )
1679+ _PyGC_GetObjects (PyInterpreterState * interp , int generation )
16821680{
16831681 assert (generation >= -1 && generation < NUM_GENERATIONS );
16841682 GCState * gcstate = & interp -> gc ;
@@ -1974,6 +1972,7 @@ _PyObject_GC_Link(PyObject *op)
19741972 gc -> _gc_next = 0 ;
19751973 gc -> _gc_prev = 0 ;
19761974 gcstate -> young .count ++ ; /* number of allocated GC objects */
1975+ gcstate -> heap_size ++ ;
19771976 if (gcstate -> young .count > gcstate -> young .threshold &&
19781977 gcstate -> enabled &&
19791978 gcstate -> young .threshold &&
@@ -2095,6 +2094,7 @@ PyObject_GC_Del(void *op)
20952094 if (gcstate -> young .count > 0 ) {
20962095 gcstate -> young .count -- ;
20972096 }
2097+ gcstate -> heap_size -- ;
20982098 PyObject_Free (((char * )op )- presize );
20992099}
21002100
0 commit comments