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:
parent
267e5bc78d
commit
e7e30a5e7d
1 changed files with 24 additions and 7 deletions
31
src/gc.c
31
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue