8000 esp32: Experiment with preferring to reserve some ESP-IDF heap. · micropython/micropython@78051fb · GitHub
[go: up one dir, main page]

Skip to content

Commit 78051fb

Browse files
committed
esp32: Experiment with preferring to reserve some ESP-IDF heap.
gc_get_max_new_split() function extended so the port knows how much memory Python needs for the current allocation to succeed. It can decide to reserve some ESP-IDF heap based on the total free heap (or potentially other considerations). Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent 9ca5958 commit 78051fb

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

ports/esp32/gccollect.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,36 @@ void gc_collect(void) {
8383

8484
#if MICROPY_GC_SPLIT_HEAP_AUTO
8585

86-
// The largest new region that is available to become Python heap is the largest
87-
// free block in the ESP-IDF system heap.
88-
size_t gc_get_max_new_split(void) {
89-
return heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT);
86+
// Unless necessary to avoid a Python MemoryError,
87+
// try to reserve this much free system heap for ESP-IDF
88+
#define RESERVE_SYSTEM_HEAP (24 * 1024)
89+
90+
size_t gc_get_max_new_split(size_t needed) {
91+
multi_heap_info_t info = { 0 };
92+
heap_caps_get_info(&info, MALLOC_CAP_DEFAULT);
93+
94+
// The largest new region that is available to become Python heap is the largest
95+
// free block in the ESP-IDF system heap...
96+
size_t max = info.largest_free_block;
97+
98+
if (max <= needed) {
99+
return max;
100+
}
101+
102+
// ... unless overall free heap is running low, in which case
103+
// prefer to save some RAM for ESP-IDF unless it's needed.
104+
if (info.total_free_bytes < max + RESERVE_SYSTEM_HEAP) {
105+
if (max > needed + RESERVE_SYSTEM_HEAP) {
106+
// Reserve some of the largest free block for the system. New Python
107+
// heap area will still be big enough for 'needed'.
108+
max -= RESERVE_SYSTEM_HEAP;
109+
} else {
110+
// Memory is really low, only allow Python exactly what it needs
111+
max = needed;
112+
}
113+
}
114+
115+
return max;
90116
}
91117

92118
#endif

py/gc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ STATIC bool gc_try_add_heap(size_t failed_alloc) {
250250
// rounding up of partial block sizes.)
251251
size_t needed = failed_alloc + MAX(2048, failed_alloc * 13 / 512);
252252

253-
size_t avail = gc_get_max_new_split();
253+
size_t avail = gc_get_max_new_split(needed);
254254

255255
DEBUG_printf("gc_try_add_heap failed_alloc " UINT_FMT ", "
256256
"needed " UINT_FMT ", avail " UINT_FMT " bytes \n",
@@ -1160,7 +1160,7 @@ void gc_dump_info(const mp_print_t *print) {
11601160
mp_printf(print, "GC: total: %u, used: %u, free: %u",
11611161
(uint)info.total, (uint)info.used, (uint)info.free);
11621162
#if MICROPY_GC_SPLIT_HEAP_AUTO
1163-
mp_printf(print, ", max new split: %u", (uint)gc_get_max_new_split());
1163+
mp_printf(print, ", max new split: %u", (uint)gc_get_max_new_split(UINT_MAX));
11641164
#endif
11651165
mp_printf(print, "\n No. of 1-blocks: %u, 2-blocks: %u, max blk sz: %u, max free sz: %u\n",
11661166
(uint)info.num_1block, (uint)info.num_2block, (uint)info.max_block, (uint)info.max_free);

py/gc.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@ void gc_add(void *start, void *end);
3939
#if MICROPY_GC_SPLIT_HEAP_AUTO
4040
// Port must implement this function to return the maximum available block of
4141
// RAM to allocate a new heap area into using MP_PLAT_ALLOC_HEAP
42-
size_t gc_get_max_new_split(void);
42+
//
43+
// 'needed' is the number of bytes Python needs from the heap for the
44+
// currently failing allocation to succeed. This can be used to tweak the result
45+
// and allow Python heap to add more or less RAM. 'needed' will also have value
46+
// UINT_MAX when called from the mem_info() function, to test the maximum available.
47+
size_t gc_get_max_new_split(size_t needed);
4348
#endif // MICROPY_GC_SPLIT_HEAP_AUTO
4449
#endif // MICROPY_GC_SPLIT_HEAP
4550

0 commit comments

Comments
 (0)
0