diff options
author | David Lechner <david@pybricks.com> | 2023-03-15 16:48:16 -0500 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2023-05-09 12:44:14 +1000 |
commit | 468ed218c954d34c1cc6affeeff4153b3f16b6b5 (patch) | |
tree | 0be7735fd4ef1a2f5c34bcb3342c4945131b1980 /py | |
parent | 7c645b52e315fa3d63bb95bb42ccf2a9c15fe21d (diff) |
py/gc: Make improvements to MICROPY_GC_HOOK_LOOP.
Changes in this commit:
- Add MICROPY_GC_HOOK_LOOP to gc_info() and gc_alloc(). Both of these can
be long running (many milliseconds) which is too long to be blocking in
some applications.
- Pass loop variable to MICROPY_GC_HOOK_LOOP(i) macro so that implementers
can use it, e.g. to improve performance by only calling a function every
X number of iterations.
- Drop outer call to MICROPY_GC_HOOK_LOOP in gc_mark_subtree().
Diffstat (limited to 'py')
-rw-r--r-- | py/gc.c | 14 | ||||
-rw-r--r-- | py/mpconfig.h | 3 |
2 files changed, 9 insertions, 8 deletions
@@ -285,10 +285,8 @@ STATIC void gc_mark_subtree(size_t block) // Start with the block passed in the argument. size_t sp = 0; for (;;) { - MICROPY_GC_HOOK_LOOP - #if !MICROPY_GC_SPLIT_HEAP - mp_state_mem_area_t * area = &MP_STATE_MEM(area); + mp_state_mem_area_t *area = &MP_STATE_MEM(area); #endif // work out number of consecutive blocks in the chain starting with this one @@ -303,7 +301,7 @@ STATIC void gc_mark_subtree(size_t block) // check this block's children void **ptrs = (void **)PTR_FROM_BLOCK(area, block); for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) { - MICROPY_GC_HOOK_LOOP + MICROPY_GC_HOOK_LOOP(i); void *ptr = *ptrs; // If this is a heap pointer that hasn't been marked, mark it and push // it's children to the stack. @@ -359,7 +357,7 @@ STATIC void gc_deal_with_stack_overflow(void) { // scan entire memory looking for blocks which have been marked but not their children for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { for (size_t block = 0; block < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { - MICROPY_GC_HOOK_LOOP + MICROPY_GC_HOOK_LOOP(block); // trace (again) if mark bit set if (ATB_GET_KIND(area, block) == AT_MARK) { #if MICROPY_GC_SPLIT_HEAP @@ -381,7 +379,7 @@ STATIC void gc_sweep(void) { int free_tail = 0; for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { for (size_t block = 0; block < area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) { - MICROPY_GC_HOOK_LOOP + MICROPY_GC_HOOK_LOOP(block); switch (ATB_GET_KIND(area, block)) { case AT_HEAD: #if MICROPY_ENABLE_FINALISER @@ -475,7 +473,7 @@ void gc_collect_root(void **ptrs, size_t len) { mp_state_mem_area_t *area = &MP_STATE_MEM(area); #endif for (size_t i = 0; i < len; i++) { - MICROPY_GC_HOOK_LOOP + MICROPY_GC_HOOK_LOOP(i); void *ptr = gc_get_ptr(ptrs, i); #if MICROPY_GC_SPLIT_HEAP mp_state_mem_area_t *area = gc_get_ptr_area(ptr); @@ -533,6 +531,7 @@ void gc_info(gc_info_t *info) { bool finish = false; info->total += area->gc_pool_end - area->gc_pool_start; for (size_t block = 0, len = 0, len_free = 0; !finish;) { + MICROPY_GC_HOOK_LOOP(block); size_t kind = ATB_GET_KIND(area, block); switch (kind) { case AT_FREE: @@ -632,6 +631,7 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { for (; area != NULL; area = NEXT_AREA(area), i = 0) { n_free = 0; for (i = area->gc_last_free_atb_index; i < area->gc_alloc_table_byte_len; i++) { + MICROPY_GC_HOOK_LOOP(i); byte a = area->gc_alloc_table_start[i]; // *FORMAT-OFF* if (ATB_0_IS_FREE(a)) { if (++n_free >= n_blocks) { i = i * BLOCKS_PER_ATB + 0; goto found; } } else { n_free = 0; } diff --git a/py/mpconfig.h b/py/mpconfig.h index 89fb733e9..f3d5ce557 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -617,8 +617,9 @@ #endif // Hook to run code during time consuming garbage collector operations +// *i* is the loop index variable (e.g. can be used to run every x loops) #ifndef MICROPY_GC_HOOK_LOOP -#define MICROPY_GC_HOOK_LOOP +#define MICROPY_GC_HOOK_LOOP(i) #endif // Whether to provide m_tracked_calloc, m_tracked_free functions |