mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Add default_commit_size to virtual.Arena
This commit is contained in:
+32
-10
@@ -17,18 +17,23 @@ Arena_Kind :: enum uint {
|
|||||||
Buffer: A single `Memory_Block` created from a user provided []byte.
|
Buffer: A single `Memory_Block` created from a user provided []byte.
|
||||||
*/
|
*/
|
||||||
Arena :: struct {
|
Arena :: struct {
|
||||||
kind: Arena_Kind,
|
kind: Arena_Kind,
|
||||||
curr_block: ^Memory_Block,
|
curr_block: ^Memory_Block,
|
||||||
total_used: uint,
|
|
||||||
total_reserved: uint,
|
total_used: uint,
|
||||||
minimum_block_size: uint,
|
total_reserved: uint,
|
||||||
temp_count: uint,
|
|
||||||
mutex: sync.Mutex,
|
default_commit_size: uint, // commit size <= reservation size
|
||||||
|
minimum_block_size: uint, // block size == total reservation
|
||||||
|
|
||||||
|
temp_count: uint,
|
||||||
|
mutex: sync.Mutex,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 1 MiB should be enough to start with
|
// 1 MiB should be enough to start with
|
||||||
DEFAULT_ARENA_STATIC_COMMIT_SIZE :: mem.Megabyte
|
DEFAULT_ARENA_STATIC_COMMIT_SIZE :: mem.Megabyte
|
||||||
|
DEFAULT_ARENA_GROWING_COMMIT_SIZE :: 8*mem.Megabyte
|
||||||
DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE :: DEFAULT_ARENA_STATIC_COMMIT_SIZE
|
DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE :: DEFAULT_ARENA_STATIC_COMMIT_SIZE
|
||||||
|
|
||||||
// 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default
|
// 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default
|
||||||
@@ -102,8 +107,20 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
|||||||
if arena.curr_block == nil || (safe_add(arena.curr_block.used, needed) or_else 0) > arena.curr_block.reserved {
|
if arena.curr_block == nil || (safe_add(arena.curr_block.used, needed) or_else 0) > arena.curr_block.reserved {
|
||||||
if arena.minimum_block_size == 0 {
|
if arena.minimum_block_size == 0 {
|
||||||
arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE
|
arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE
|
||||||
|
arena.minimum_block_size = mem.align_formula_uint(arena.minimum_block_size, DEFAULT_PAGE_SIZE)
|
||||||
|
}
|
||||||
|
if arena.default_commit_size == 0 {
|
||||||
|
arena.default_commit_size = min(DEFAULT_ARENA_GROWING_COMMIT_SIZE, arena.minimum_block_size)
|
||||||
|
arena.default_commit_size = mem.align_formula_uint(arena.default_commit_size, DEFAULT_PAGE_SIZE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if arena.default_commit_size != 0 {
|
||||||
|
arena.default_commit_size, arena.minimum_block_size =
|
||||||
|
min(arena.default_commit_size, arena.minimum_block_size),
|
||||||
|
max(arena.default_commit_size, arena.minimum_block_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
needed = max(needed, arena.default_commit_size)
|
||||||
block_size := max(needed, arena.minimum_block_size)
|
block_size := max(needed, arena.minimum_block_size)
|
||||||
|
|
||||||
new_block := memory_block_alloc(needed, block_size, alignment, {}) or_return
|
new_block := memory_block_alloc(needed, block_size, alignment, {}) or_return
|
||||||
@@ -113,7 +130,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
|||||||
}
|
}
|
||||||
|
|
||||||
prev_used := arena.curr_block.used
|
prev_used := arena.curr_block.used
|
||||||
data, err = alloc_from_memory_block(arena.curr_block, size, alignment)
|
data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=arena.default_commit_size)
|
||||||
arena.total_used += arena.curr_block.used - prev_used
|
arena.total_used += arena.curr_block.used - prev_used
|
||||||
case .Static:
|
case .Static:
|
||||||
if arena.curr_block == nil {
|
if arena.curr_block == nil {
|
||||||
@@ -122,12 +139,17 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
|||||||
}
|
}
|
||||||
arena_init_static(arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return
|
arena_init_static(arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return
|
||||||
}
|
}
|
||||||
fallthrough
|
if arena.curr_block == nil {
|
||||||
|
return nil, .Out_Of_Memory
|
||||||
|
}
|
||||||
|
data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=arena.default_commit_size)
|
||||||
|
arena.total_used = arena.curr_block.used
|
||||||
|
|
||||||
case .Buffer:
|
case .Buffer:
|
||||||
if arena.curr_block == nil {
|
if arena.curr_block == nil {
|
||||||
return nil, .Out_Of_Memory
|
return nil, .Out_Of_Memory
|
||||||
}
|
}
|
||||||
data, err = alloc_from_memory_block(arena.curr_block, size, alignment)
|
data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=0)
|
||||||
arena.total_used = arena.curr_block.used
|
arena.total_used = arena.curr_block.used
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ memory_block_alloc :: proc(committed, reserved: uint, alignment: uint = 0, flags
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) -> (data: []byte, err: Allocator_Error) {
|
alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint, default_commit_size: uint = 0) -> (data: []byte, err: Allocator_Error) {
|
||||||
calc_alignment_offset :: proc "contextless" (block: ^Memory_Block, alignment: uintptr) -> uint {
|
calc_alignment_offset :: proc "contextless" (block: ^Memory_Block, alignment: uintptr) -> uint {
|
||||||
alignment_offset := uint(0)
|
alignment_offset := uint(0)
|
||||||
ptr := uintptr(block.base[block.used:])
|
ptr := uintptr(block.base[block.used:])
|
||||||
@@ -123,7 +123,7 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint)
|
|||||||
return alignment_offset
|
return alignment_offset
|
||||||
|
|
||||||
}
|
}
|
||||||
do_commit_if_necessary :: proc(block: ^Memory_Block, size: uint) -> (err: Allocator_Error) {
|
do_commit_if_necessary :: proc(block: ^Memory_Block, size: uint, default_commit_size: uint) -> (err: Allocator_Error) {
|
||||||
if block.committed - block.used < size {
|
if block.committed - block.used < size {
|
||||||
pmblock := (^Platform_Memory_Block)(block)
|
pmblock := (^Platform_Memory_Block)(block)
|
||||||
base_offset := uint(uintptr(pmblock.block.base) - uintptr(pmblock))
|
base_offset := uint(uintptr(pmblock.block.base) - uintptr(pmblock))
|
||||||
@@ -133,7 +133,7 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint)
|
|||||||
extra_size := max(size, block.committed>>1)
|
extra_size := max(size, block.committed>>1)
|
||||||
platform_total_commit := base_offset + block.used + extra_size
|
platform_total_commit := base_offset + block.used + extra_size
|
||||||
platform_total_commit = align_formula(platform_total_commit, DEFAULT_PAGE_SIZE)
|
platform_total_commit = align_formula(platform_total_commit, DEFAULT_PAGE_SIZE)
|
||||||
platform_total_commit = min(platform_total_commit, pmblock.reserved)
|
platform_total_commit = min(max(platform_total_commit, default_commit_size), pmblock.reserved)
|
||||||
|
|
||||||
assert(pmblock.committed <= pmblock.reserved)
|
assert(pmblock.committed <= pmblock.reserved)
|
||||||
assert(pmblock.committed < platform_total_commit)
|
assert(pmblock.committed < platform_total_commit)
|
||||||
@@ -163,7 +163,7 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert(block.committed <= block.reserved)
|
assert(block.committed <= block.reserved)
|
||||||
do_commit_if_necessary(block, size) or_return
|
do_commit_if_necessary(block, size, default_commit_size) or_return
|
||||||
|
|
||||||
data = block.base[block.used+alignment_offset:][:min_size]
|
data = block.base[block.used+alignment_offset:][:min_size]
|
||||||
block.used += size
|
block.used += size
|
||||||
|
|||||||
Reference in New Issue
Block a user