From 1bcf7d8ae698be75e3ee9189d4f7c15267abfd35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 9 Jun 2026 19:56:34 +0200 Subject: [PATCH] Optimize arena_push() to do 1 commit when pushed size is larger than commit siz --- src/arena.c | 55 +++++++++++++++++++++++++++++++++++------------------ src/arena.h | 1 + 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/arena.c b/src/arena.c index e3bdf23..9891c05 100644 --- a/src/arena.c +++ b/src/arena.c @@ -2,44 +2,57 @@ #include "base_core.h" #include "platform.h" - -static MemoryBlock *memoryblock_allocate(U32 size, U32 commit_size, U32 page_size) +typedef struct MemoryBlockOptions MemoryBlockOptions; +struct MemoryBlockOptions { + U32 size; + U32 commit_size; + U32 commit_now_size; + U32 page_size; +}; +static U32 idx; +static MemoryBlock *memoryblock_allocate(const MemoryBlockOptions *opts) { - U32 aligned_size = AlignUpPow2(size, page_size); - U32 aligned_commit_size = AlignUpPow2(commit_size, page_size); + U32 aligned_size = AlignUpPow2(opts->size, opts->page_size); + U32 aligned_commit_size = AlignUpPow2(opts->commit_size, opts->page_size); + U32 aligned_commit_now_size = AlignUpPow2(opts->commit_now_size, opts->page_size); MemoryBlock *block = memory_reserve(aligned_size); Assert(block != NULL); - memory_commit(block, aligned_commit_size); + memory_commit(block, aligned_commit_now_size); block->base = (U8 *)block; block->size = aligned_size; block->first_free = MemoryBlock_Header_Size; block->arena_offset = 0; block->prev = NULL; - block->committed_end = aligned_commit_size; + block->committed_end = aligned_commit_now_size; + block->idx = idx++; ASAN_POISON_MEMORY_REGION(block->base, block->size); ASAN_UNPOISON_MEMORY_REGION(block, MemoryBlock_Header_Size); return block; } -void arena_init(Arena *arena, const ArenaOptions *params) +void arena_init(Arena *arena, const ArenaOptions *opts) { U32 page_size = platform_page_size(); - Assert(params->size > MemoryBlock_Header_Size); - Assert(params->size < (U32_Max - page_size)); // Reserving last piece so our math doesn't overflow - Assert(params->commit_size > 0); - Assert(params->commit_size <= params->size); + Assert(opts->size > MemoryBlock_Header_Size); + Assert(opts->size < (U32_Max - page_size)); // Reserving last piece so our math doesn't overflow + Assert(opts->commit_size > 0); + Assert(opts->commit_size <= opts->size); + MemoryBlockOptions mb_opts; + mb_opts.page_size = page_size; + mb_opts.commit_size = opts->commit_size; + mb_opts.size = opts->size; + mb_opts.commit_now_size = opts->commit_size; + MemoryBlock *block = memoryblock_allocate(&mb_opts); - MemoryBlock *block = memoryblock_allocate(params->size, params->commit_size, page_size); - - arena->flags = params->flags; + arena->flags = opts->flags; arena->checkpoint_level = 0; arena->current = block; - arena->block_size = params->size; - arena->commit_size = params->commit_size; + arena->block_size = opts->size; + arena->commit_size = opts->commit_size; arena->page_size = page_size; } @@ -72,9 +85,15 @@ void *arena_push(Arena *arena, U32 size, U32 align) block_size = AlignUpPow2(size + MemoryBlock_Header_Size,align); new_commit_size = block_size; } + U32 commit_now_size = Max(new_commit_size, size); - MemoryBlock *new_block = memoryblock_allocate(block_size, new_commit_size, arena->page_size); - // base_pos tracks the virtual absolute position within an arena + MemoryBlockOptions mb_opts; + mb_opts.page_size = arena->page_size; + mb_opts.commit_size = new_commit_size; + mb_opts.size = block_size; + mb_opts.commit_now_size = commit_now_size; + MemoryBlock *new_block = memoryblock_allocate(&mb_opts); + // arena_offset tracks the virtual absolute position within an arena // This is not a contiguous space, we use it to free blocks when popping the arena new_block->arena_offset = block->arena_offset + block->size; new_block->prev = block; diff --git a/src/arena.h b/src/arena.h index 934c2c8..239e7f9 100644 --- a/src/arena.h +++ b/src/arena.h @@ -18,6 +18,7 @@ struct MemoryBlock { U64 arena_offset; // absolute offset of base relative to the first linked arena U32 committed_end; // end of committed region. Will be page aligned MemoryBlock *prev; + U32 idx; }; typedef struct Arena Arena;