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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy