Skip to content

Commit 49b47fa

Browse files
committed
Merge young gen and increment before scanning.
1 parent 03ea080 commit 49b47fa

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

Python/gc.c

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@ update_refs(PyGC_Head *containers)
474474

475475
while (gc != containers) {
476476
next = GC_NEXT(gc);
477-
assert(!_Py_IsImmortal(FROM_GC(gc)));
477+
PyObject *op = FROM_GC(gc);
478+
assert(!_Py_IsImmortal(op));
478479
gc_reset_refs(gc, Py_REFCNT(op));
479480
/* Python's cyclic gc should never see an incoming refcount
480481
* of 0: if something decref'ed to 0, it should have been
@@ -1369,7 +1370,6 @@ completed_cycle(GCState *gcstate)
13691370
{
13701371
PyGC_Head *not_visited = &gcstate->old[gcstate->visited_space^1].head;
13711372
assert(gc_list_is_empty(not_visited));
1372-
assert(gc_list_is_empty(&gcstate->young.head));
13731373
gcstate->visited_space = flip_old_space(gcstate->visited_space);
13741374
if (gcstate->work_to_do > 0) {
13751375
gcstate->work_to_do = 0;
@@ -1380,20 +1380,26 @@ static void
13801380
gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
13811381
{
13821382
GCState *gcstate = &tstate->interp->gc;
1383-
assert(gc_list_is_empty(&gcstate->young.head));
1384-
if (gcstate->work_to_do <= 0) {
1385-
/* No work to do */
1386-
return;
1387-
}
13881383
PyGC_Head *not_visited = &gcstate->old[gcstate->visited_space^1].head;
13891384
PyGC_Head *visited = &gcstate->old[gcstate->visited_space].head;
13901385
PyGC_Head increment;
13911386
gc_list_init(&increment);
1392-
if (gc_list_is_empty(not_visited)) {
1393-
completed_cycle(gcstate);
1394-
return;
1395-
}
13961387
Py_ssize_t region_size = 0;
1388+
gc_list_merge(&gcstate->young.head, &increment);
1389+
gcstate->young.count = 0;
1390+
if (gcstate->visited_space) {
1391+
/* objects in visited space have bit set, so we set it here */
1392+
region_size = gc_list_set_space(&increment, 1);
1393+
}
1394+
else {
1395+
PyGC_Head *gc;
1396+
for (gc = GC_NEXT(&increment); gc != &increment; gc = GC_NEXT(gc)) {
1397+
#ifdef GC_DEBUG
1398+
assert(gc_old_space(gc) == 0);
1399+
#endif
1400+
region_size++;
1401+
}
1402+
}
13971403
while (region_size < gcstate->work_to_do) {
13981404
if (gc_list_is_empty(not_visited)) {
13991405
break;
@@ -1403,13 +1409,19 @@ gc_collect_increment(PyThreadState *tstate, struct gc_collection_stats *stats)
14031409
gc_set_old_space(gc, gcstate->visited_space);
14041410
region_size += expand_region_transitively_reachable(&increment, gc, gcstate);
14051411
}
1406-
assert(region_size = gc_list_size(&increment));
1412+
assert(region_size == gc_list_size(&increment));
14071413
GC_STAT_ADD(1, objects_queued, region_size);
14081414
PyGC_Head survivors;
14091415
gc_list_init(&survivors);
14101416
gc_collect_region(tstate, &increment, &survivors, UNTRACK_TUPLES, stats);
14111417
gc_list_merge(&survivors, visited);
14121418
assert(gc_list_is_empty(&increment));
1419+
Py_ssize_t survivor_count = gc_list_size(&survivors);
1420+
Py_ssize_t scale_factor = gcstate->old[0].threshold;
1421+
if (scale_factor < 1) {
1422+
scale_factor = 1;
1423+
}
1424+
gcstate->work_to_do += survivor_count + survivor_count * SCAN_RATE_MULTIPLIER / scale_factor;
14131425
gcstate->work_to_do -= region_size;
14141426
validate_old(gcstate);
14151427
add_stats(gcstate, 1, stats);
@@ -1448,7 +1460,7 @@ gc_collect_full(PyThreadState *tstate,
14481460
gcstate->old[1].count = 0;
14491461

14501462
gcstate->work_to_do = - gcstate->young.threshold * 2;
1451-
clear_freelists(tstate->interp);
1463+
_PyGC_ClearAllFreeLists(tstate->interp);
14521464
validate_old(gcstate);
14531465
add_stats(gcstate, 2, stats);
14541466
}
@@ -1768,7 +1780,6 @@ _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason)
17681780
gc_collect_young(tstate, &stats);
17691781
break;
17701782
case 1:
1771-
gc_collect_young(tstate, &stats);
17721783
gc_collect_increment(tstate, &stats);
17731784
break;
17741785
case 2:

0 commit comments

Comments
 (0)