Skip to content

Commit b796e3d

Browse files
committed
py: Reduce fragmentation of GC heap.
Recent speed up of GC allocation made the GC have a fragmented heap. This patch restores "original fragmentation behaviour" whilst still retaining relatively fast allocation. This patch works because there is always going to be a single block allocated now and then, which advances the gc_last_free_atb_index pointer often enough so that the whole heap doesn't need scanning. Should address issue adafruit#836.
1 parent a97e091 commit b796e3d

File tree

1 file changed

+7
-9
lines changed

1 file changed

+7
-9
lines changed

py/gc.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -386,13 +386,6 @@ void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser) {
386386
if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; }
387387
if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; }
388388
}
389-
for (i = 0; i < gc_last_free_atb_index; i++) {
390-
byte a = gc_alloc_table_start[i];
391-
if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; }
392-
if (ATB_1_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 1; goto found; } } else { n_free = 0; }
393-
if (ATB_2_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 2; goto found; } } else { n_free = 0; }
394-
if (ATB_3_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 3; goto found; } } else { n_free = 0; }
395-
}
396389

397390
// nothing found!
398391
if (collected) {
@@ -409,8 +402,13 @@ void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser) {
409402
end_block = i;
410403
start_block = i - n_free + 1;
411404

412-
// set last free ATB index to last block we found, for start of next scan
413-
gc_last_free_atb_index = i / BLOCKS_PER_ATB;
405+
// Set last free ATB index to block after last block we found, for start of
406+
// next scan. To reduce fragmentation, we only do this if we were looking
407+
// for a single free block, which guarantees that there are no free blocks
408+
// before this one.
409+
if (n_free == 1) {
410+
gc_last_free_atb_index = (i + 1) / BLOCKS_PER_ATB;
411+
}
414412

415413
// mark first block as used head
416414
ATB_FREE_TO_HEAD(start_block);

0 commit comments

Comments
 (0)