From c38117e8a1f5a0d255c6680619f3bb8a553aaa99 Mon Sep 17 00:00:00 2001 From: Max Regan Date: Wed, 30 Nov 2022 20:42:44 -0500 Subject: [PATCH] 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 --- src/arena.c | 58 ++++++++++++++++------------------------------------- src/types.h | 2 +- 2 files changed, 18 insertions(+), 42 deletions(-) diff --git a/src/arena.c b/src/arena.c index b9fd61c..eed67bf 100644 --- a/src/arena.c +++ b/src/arena.c @@ -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,45 +50,25 @@ 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); - - - 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; - - arena->used_map[int_index] |= 1 << bit_index; - - void *ret = (char *) arena->objects + (arena->next_free * arena->object_size); - arena->next_free = -1; - - 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; + size_t index = arena->last_allocated_index; + do { + // TODO: Restructure for speed with ffs + index++; + if (index == arena->capacity) { + index = 0; } - 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; + size_t int_index = index / INT_BITS; + size_t bit_index = index % INT_BITS; - return (char *) arena->objects + (index * arena->object_size); - } + if (!(arena->used_map[int_index] & 1 << bit_index)) { + arena->used_map[int_index] |= 1 << bit_index; + arena->last_allocated_index = 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; } diff --git a/src/types.h b/src/types.h index 631e990..729d788 100644 --- a/src/types.h +++ b/src/types.h @@ -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;