From e7e30a5e7d4247eb0952e1fece61c675e99df2d9 Mon Sep 17 00:00:00 2001 From: Laria Carolin Chabowski Date: Fri, 12 Jul 2024 23:12:25 +0200 Subject: [PATCH] gc: Remember position when searching for a free slot It's very likely that if we find a free slot, another free slot will be nearby. So let's remember the position in the block and make sure the block where we found a free slot will be checked first next time. This improves performance in mandelbrot.apfl by about 40% :) --- src/gc.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/gc.c b/src/gc.c index 621784d..1e700e0 100644 --- a/src/gc.c +++ b/src/gc.c @@ -46,6 +46,7 @@ struct gc_object { struct gc_block { struct gc_object objects[GC_OBJECTS_PER_BLOCK]; struct gc_block *next; + size_t check_next; }; static void * @@ -120,6 +121,7 @@ new_block(struct gc *gc) block->objects[i] = (struct gc_object) { .status = GC_STATUS_FREE }; } block->next = NULL; + block->check_next = 0; return block; } @@ -127,17 +129,28 @@ new_block(struct gc *gc) static struct gc_object * new_object_inner(struct gc *gc) { - struct gc_block *cur = gc->block; + struct gc_block **cur = &gc->block; - while (cur != NULL) { - struct gc_block *block = cur; - for (size_t i = 0; i < GC_OBJECTS_PER_BLOCK; i++) { - if (block->objects[i].status == GC_STATUS_FREE) { - return &block->objects[i]; + bool walked_to_next_block = false; + while (*cur != NULL) { + struct gc_block *block = *cur; + for (; block->check_next < GC_OBJECTS_PER_BLOCK; block->check_next++) { + if (block->objects[block->check_next].status == GC_STATUS_FREE) { + if (walked_to_next_block) { + // Move this block to the front of the linked list. It + // likely has more free slots and should be checked first + struct gc_block *b = *cur; + *cur = b->next; + b->next = gc->block; + gc->block = b; + } + + return &block->objects[block->check_next]; } } - cur = block->next; + cur = &block->next; + walked_to_next_block = true; } struct gc_block *nb = new_block(gc); @@ -449,6 +462,10 @@ sweep(apfl_ctx ctx) reclaimed_blocks++; #endif } else { + // Start checking from the beginning of the block again when + // searching for a free slot + block->check_next = 0; + cur = &block->next; } }