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% :)
This commit is contained in:
Laria 2024-07-12 23:12:25 +02:00
parent 267e5bc78d
commit e7e30a5e7d

View file

@ -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;
}
}