Start to setup the other allocators I'm going to roll my own of, also created a string interning file

This commit is contained in:
Edward R. Gonzalez 2024-03-05 10:41:42 -05:00
parent 898f359470
commit 3c8abc5333
4 changed files with 149 additions and 0 deletions

45
code/grime_arena.odin Normal file
View File

@ -0,0 +1,45 @@
/*
The default arena allocator Odin provides does fragmented resizes even for the last most allocated block getting resized.
This is an alternative to alleviates that.
*/
package sectr
ArenaFixedHeader :: struct {
data : []byte,
offset : uint,
peak_used : uint,
}
ArenaFixed :: struct {
using header : ^ArenaFixedHeader,
}
arena_fixed_init :: proc( backing : []byte ) -> (arena : ArenaFixed) {
header_size := size_of(ArenaFixedHeader)
verify(len(backing) >= (header_size + Kilobyte), "Attempted to init an arena with less than kilobyte of memory...")
arena.header = cast(^ArenaFixedHeader) raw_data(backing)
using arena.header
data_ptr := cast([^]byte) (cast( [^]ArenaFixedHeader) arena.header)[ 1:]
data = slice_ptr( data_ptr, len(backing) - header_size )
offset = 0
peak_used = 0
return
}
arena_fixed_allocator_proc :: proc(
allocator_data : rawptr,
mode : AllocatorMode,
size : int,
alignment : int,
old_memory : rawptr,
old_size : int,
location := #caller_location
) -> ([]byte, AllocatorError)
{
return nil, .Out_Of_Memory
}

View File

@ -0,0 +1,45 @@
/*
This is a pool allocator setup to grow incrementally via buckets.
Buckets are stored in singly-linked lists so that they be allocated non-contiguous
*/
package sectr
Pool :: struct {
using header : ^PoolHeader,
}
PoolHeader :: struct {
backing : Allocator,
block_size : uint,
bucket_capacity : uint,
out_band_size : uint,
alignment : uint,
free_list : LL_Node( [^]byte),
buckets : LL_Node( [^]byte),
current_bucket : ^byte,
}
PoolBucket :: struct ( $ Type : typeid) {
blocks : [^]Type,
}
pool_allocator :: proc ( using self : Pool ) -> (allocator : Allocator) {
allocator.procedure = pool_allocator_proc
allocator.data = self.header
return
}
pool_allocator_proc :: proc(
allocator_data : rawptr,
mode : AllocatorMode,
size : int,
alignment : int,
old_memory : rawptr,
old_size : int,
loc := #caller_location
) -> ([]byte, AllocatorError)
{
return nil, AllocatorError.Mode_Not_Implemented
}

View File

@ -1,5 +1,63 @@
/* Slab Allocator
These are a collection of pool allocators serving as a general way
to allocate a large amount of dynamic sized data.
The usual use case for this is an arena, stack,
or dedicated pool allocator fail to be enough to handle a data structure
that either is too random with its size (ex: strings)
or is intended to grow an abitrary degree with an unknown upper bound (dynamic arrays, and hashtables).
The protototype will use slab allocators for two purposes:
* String interning
* General purpose set for handling large arrays & hash tables within some underlying arena or stack.
Technically speaking the general purpose situations can instead be grown on demand
with a dedicated segement of vmem, however this might be overkill
if the worst case buckets allocated are < 500 mb for most app usage.
The slab allocators are expected to hold growable pool allocators,
where each pool stores a 'bucket' of fixed-sized blocks of memory.
When a pools bucket is full it will request another bucket from its arena
for permanent usage within the arena's lifetime.
A freelist is tracked for free-blocks for each pool (provided by the underlying pool allocator)
A slab starts out with pools initialized with no buckets and grows as needed.
When a slab is initialized the slab policy is provided to know how many size-classes there should be
which each contain the ratio of bucket to block size.
Strings Slab pool size-classes (bucket:block ratio) are as follows:
16 mb : 64 b = 262,144 blocks
8 mb : 128 b = 8192 blocks
8 mb : 256 b = 8192 blocks
8 mb : 1 kb = 8192 blocks
16 mb : 4 kb = 4096 blocks
32 mb : 16 kb = 4096 blocks
32 mb : 32 kb = 4096 blocks
256 mb : 64 kb =
512 mb : 128 kb =
*/
package sectr
SlabSizeClass :: struct {
bucket : uint,
block : uint,
}
Slab_Max_Size_Classes :: 32
SlabPolicy :: [Slab_Max_Size_Classes]SlabSizeClass
SlabHeader :: struct {
policy : SlabPolicy,
pools : [Slab_Max_Size_Classes]Pool,
}
Slab :: struct {
using header : SlabHeader,
}
slab_init_reserve :: proc( ) -> ( Slab )
{
return {}
}

View File

@ -0,0 +1 @@
package sectr