Skip to content

Commit 60a248b

Browse files
committed
Revert "pythonGH-117108: Change the size of the GC increment to about 1% of the total heap size. (pythonGH-117120)"
This reverts commit e28477f.
1 parent 2992289 commit 60a248b

5 files changed

Lines changed: 28 additions & 32 deletions

File tree

Include/internal/pycore_gc.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,6 @@ struct _gc_runtime_state {
315315
/* a list of callbacks to be invoked when collection is performed */
316316
PyObject *callbacks;
317317

318-
Py_ssize_t heap_size;
319318
Py_ssize_t work_to_do;
320319
/* Which of the old spaces is the visited space */
321320
int visited_space;
@@ -363,7 +362,7 @@ extern void _PyGC_Unfreeze(PyInterpreterState *interp);
363362
/* Number of frozen objects */
364363
extern Py_ssize_t _PyGC_GetFreezeCount(PyInterpreterState *interp);
365364

366-
extern PyObject *_PyGC_GetObjects(PyInterpreterState *interp, int generation);
365+
extern PyObject *_PyGC_GetObjects(PyInterpreterState *interp, Py_ssize_t generation);
367366
extern PyObject *_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs);
368367

369368
// Functions to clear types free lists

Lib/test/test_gc.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,31 +1122,28 @@ def make_ll(depth):
11221122
head = LinkedList(head, head.prev)
11231123
return head
11241124

1125-
head = make_ll(1000)
1126-
count = 1000
1125+
head = make_ll(10000)
1126+
count = 10000
11271127

1128-
# There will be some objects we aren't counting,
1129-
# e.g. the gc stats dicts. This test checks
1130-
# that the counts don't grow, so we try to
1131-
# correct for the uncounted objects
1132-
# This is just an estimate.
1133-
CORRECTION = 20
1128+
# We expect the counts to go negative eventually
1129+
# as there will some objects we aren't counting,
1130+
# e.g. the gc stats dicts. The test merely checks
1131+
# that the counts don't grow.
11341132

11351133
enabled = gc.isenabled()
11361134
gc.enable()
11371135
olds = []
1138-
for i in range(20_000):
1139-
newhead = make_ll(20)
1140-
count += 20
1136+
for i in range(1000):
1137+
newhead = make_ll(200)
1138+
count += 200
11411139
newhead.surprise = head
11421140
olds.append(newhead)
1143-
if len(olds) == 20:
1141+
if len(olds) == 50:
11441142
stats = gc.get_stats()
11451143
young = stats[0]
11461144
incremental = stats[1]
11471145
old = stats[2]
11481146
collected = young['collected'] + incremental['collected'] + old['collected']
1149-
count += CORRECTION
11501147
live = count - collected
11511148
self.assertLess(live, 25000)
11521149
del olds[:]

Modules/gcmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ gc_get_objects_impl(PyObject *module, Py_ssize_t generation)
326326
}
327327

328328
PyInterpreterState *interp = _PyInterpreterState_GET();
329-
return _PyGC_GetObjects(interp, (int)generation);
329+
return _PyGC_GetObjects(interp, generation);
330330
}
331331

332332
/*[clinic input]

Python/gc.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

12341233
static 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

12651264
static void
12661265
add_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
13831382
static void
13841383
completed_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

13941393
static 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

16751677
PyObject *
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

Python/gc_free_threading.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,7 @@ visit_get_objects(const mi_heap_t *heap, const mi_heap_area_t *area,
13771377
}
13781378

13791379
PyObject *
1380-
_PyGC_GetObjects(PyInterpreterState *interp, int generation)
1380+
_PyGC_GetObjects(PyInterpreterState *interp, Py_ssize_t generation)
13811381
{
13821382
PyObject *result = PyList_New(0);
13831383
if (!result) {

0 commit comments

Comments
 (0)