Arena allocators pre-allocate large blocks of contiguous memory up front. Instead of deallocating individual objects, the entire arena (memory block) is reset or freed at once. This is much faster () than dynamically deallocating. Allocation time is also reduced to a simple pointer addition ( operation)
Pros
- Allocating and deallocating memory is instant (pointer bumps).
- Spatial Locality is very good because objects are allocated sequentially in contiguous memory.
- There are no memory leaks because you don’t manage objects individually with free().
- No internal heap fragmentation.
Cons
- There is no individual deallocation. You cannot free specific objects so objects remain in memory until the entire arena is reset.
- If the arena is sized too large or if it isn’t reset frequently enough, it can hold onto large amounts of unused memory.
- It only works well for data that all shares the exact same lifecycle
Simple implementation in C:
typedef struct {
uint8_t *buffer; // The contiguous byte pool
size_t capacity; // Total size of the buffer
size_t offset; // Current allocation cursor (offset from start)
} Arena;
Arena arena_init(size_t capacity) {
Arena a = { .size = capacity, .offset = 0 };
a.buffer = malloc(capacity);
return a;
}
void *arena_alloc(Arena *a, size_t size) {
// Basic alignment (e.g., 8 bytes) is often necessary in practice
size_t aligned_size = (size + 7) & ~7;
if (a->offset + aligned_size <= a->size) {
void *ptr = &a->buffer[a->offset];
a->offset += aligned_size;
return ptr;
} return NULL; // Out of memory
}
// Reset the entire arena for reuse
void arena_reset(Arena *a) {
a->offset = 0;
}