Remove cache, rotate arena_get start scan index

This yields a ~23% overall performance improvment. It operates on the
idea that always iterating from the beginning will constantly get slower
as more objects are allocated- the free objects have higher and higher
indices. Instead, rotate around the arena so we
This commit is contained in:
2022-11-30 20:42:44 -05:00
parent d77ca22f5f
commit c38117e8a1
2 changed files with 18 additions and 42 deletions

View File

@@ -20,7 +20,7 @@ struct ucl_arena *ucl_arena_create(size_t object_size, size_t capacity) {
arena->capacity = capacity;
arena->objects = malloc(capacity * object_size);
arena->used_map = malloc(used_map_size);
arena->next_free = 0;
arena->last_allocated_index = 0;
arena->stats.used = 0;
arena->stats.freed = 0;
@@ -50,46 +50,26 @@ void ucl_arena_map(struct ucl_arena *arena, void (*map_function)(struct ucl_aren
void *ucl_arena_get(struct ucl_arena *arena) {
int used_map_ints = DIV_ROUND_UP(arena->capacity, INT_BITS);
size_t index = arena->last_allocated_index;
do {
// TODO: Restructure for speed with ffs
index++;
if (index == arena->capacity) {
index = 0;
}
size_t int_index = index / INT_BITS;
size_t bit_index = index % INT_BITS;
if (arena->next_free != -1) {
// Cache hit
/* unsigned int int_index = arena->next_free / INT_BITS; */
/* unsigned int bit_index = arena->next_free % INT_BITS; */
unsigned int int_index = arena->next_free >> 5;
unsigned int bit_index = arena->next_free & 31;
if (!(arena->used_map[int_index] & 1 << bit_index)) {
arena->used_map[int_index] |= 1 << bit_index;
void *ret = (char *) arena->objects + (arena->next_free * arena->object_size);
arena->next_free = -1;
arena->last_allocated_index = index;
arena->stats.used += 1;
return ret;
}
// Cache miss
for (int i = 0; i < used_map_ints; i++ ) {
// TODO: Maybe keep a cache of available used_map_ints
int map = arena->used_map[i];
if (!(~map)) {
continue;
}
unsigned int bit_index = __builtin_ffs(~map) - 1;
unsigned int index = bit_index + INT_BITS * i;
if (index >= arena->capacity) {
// This might happen in the last used_map_int when (capacity % int_bits != 0)
return NULL;
}
arena->used_map[i] |= 1 << bit_index;
arena->stats.used += 1;
return (char *) arena->objects + (index * arena->object_size);
}
} while (index != arena->last_allocated_index);
return NULL;
}
@@ -113,10 +93,6 @@ void ucl_arena_put(struct ucl_arena *arena, void *object) {
arena->used_map[int_index] &= ~(1 << bit_index);
/* if (arena->next_free == -1) { */
arena->next_free = index;
/* } */
arena->stats.used -= 1;
arena->stats.freed += 1;
}

View File

@@ -56,7 +56,7 @@ struct ucl_arena {
void *objects;
int *used_map;
/** Cache of size 1 **/
int next_free;
size_t last_allocated_index;
struct {
size_t used;