summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2023-12-18 13:32:36 +1100
committerDamien George <damien@micropython.org>2023-12-19 18:34:23 +1100
commit97b13132b129963a48d8b7d2e44c932cc73f7db3 (patch)
tree9a55dd37eb43bc8fadb905dbc79a6c9cfe6ffd14
parent3270d856fda58585d44dd05aefa7a95551fa76cc (diff)
py/gc: Improve calculation of new heap size in split-heap-auto mode.
There are two main changes here to improve the calculation of the size of the next heap area when automatically expanding the heap: - Compute the existing total size by counting the total number of GC blocks, and then using that to compute the corresponding number of bytes. - Round the bytes value up to the nearest multiple of BYTES_PER_BLOCK. This makes the calculation slightly simpler and more accurate, and makes sure that, in the case of growing from one area to two areas, the number of bytes allocated from the system for the second area is the same as the first. For example on esp32 with an initial area size of 65536 bytes, the subsequent allocation is also 65536 bytes. Previously it was a number that was not even a multiple of 2. Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--py/gc.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/py/gc.c b/py/gc.c
index 80e5f8036..b6969dfd4 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -282,14 +282,28 @@ STATIC bool gc_try_add_heap(size_t failed_alloc) {
// - If the new heap won't fit in the available free space, add the largest
// new heap that will fit (this may lead to failed system heap allocations
// elsewhere, but some allocation will likely fail in this circumstance!)
- size_t total_heap = 0;
+
+ // Compute total number of blocks in the current heap.
+ size_t total_blocks = 0;
for (mp_state_mem_area_t *area = &MP_STATE_MEM(area);
area != NULL;
area = NEXT_AREA(area)) {
- total_heap += area->gc_pool_end - area->gc_alloc_table_start;
- total_heap += ALLOC_TABLE_GAP_BYTE + sizeof(mp_state_mem_area_t);
+ total_blocks += area->gc_alloc_table_byte_len * BLOCKS_PER_ATB;
}
+ // Compute bytes needed to build a heap with total_blocks blocks.
+ size_t total_heap =
+ total_blocks / BLOCKS_PER_ATB
+ #if MICROPY_ENABLE_FINALISER
+ + total_blocks / BLOCKS_PER_FTB
+ #endif
+ + total_blocks * BYTES_PER_BLOCK
+ + ALLOC_TABLE_GAP_BYTE
+ + sizeof(mp_state_mem_area_t);
+
+ // Round up size to the nearest multiple of BYTES_PER_BLOCK.
+ total_heap = (total_heap + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1));
+
DEBUG_printf("total_heap " UINT_FMT " bytes\n", total_heap);
size_t to_alloc = MIN(avail, MAX(total_heap, needed));