More fixes & performance improvements
Still havent figured out the realloc issue with virtual arenas... But the fixes the slab perforamnce mitigate it at least.
This commit is contained in:
parent
8b8c4948ad
commit
b4c6fd1866
@ -249,8 +249,8 @@ reload :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem,
|
||||
// Thankfully persistent dynamic allocations are rare, and thus we know exactly which ones they are.
|
||||
|
||||
font_provider_data := & state.font_provider_data
|
||||
font_provider_data.font_cache.hashes.allocator = persistent_slab_allocator()
|
||||
font_provider_data.font_cache.entries.allocator = persistent_slab_allocator()
|
||||
font_provider_data.font_cache.hashes.backing = persistent_slab_allocator()
|
||||
font_provider_data.font_cache.entries.backing = persistent_slab_allocator()
|
||||
|
||||
ui_reload( & get_state().project.workspace.ui, cache_allocator = persistent_slab_allocator() )
|
||||
|
||||
|
@ -37,6 +37,7 @@ import "core:mem"
|
||||
AllocatorModeSet :: mem.Allocator_Mode_Set
|
||||
alloc :: mem.alloc
|
||||
alloc_bytes :: mem.alloc_bytes
|
||||
alloc_bytes_non_zeroed :: mem.alloc_bytes_non_zeroed
|
||||
Arena :: mem.Arena
|
||||
arena_allocator :: mem.arena_allocator
|
||||
arena_init :: mem.arena_init
|
||||
@ -46,6 +47,7 @@ import "core:mem"
|
||||
is_power_of_two_uintptr :: mem.is_power_of_two
|
||||
ptr_offset :: mem.ptr_offset
|
||||
resize :: mem.resize
|
||||
reisze_non_zeroed :: mem.default_resize_bytes_align_non_zeroed
|
||||
slice_ptr :: mem.slice_ptr
|
||||
TrackingAllocator :: mem.Tracking_Allocator
|
||||
tracking_allocator :: mem.tracking_allocator
|
||||
|
@ -8,14 +8,14 @@ import "core:mem"
|
||||
import "core:slice"
|
||||
|
||||
// Array :: struct ( $ Type : typeid ) {
|
||||
// allocator : Allocator,
|
||||
// bakcing : Allocator,
|
||||
// capacity : u64,
|
||||
// num : u64,
|
||||
// data : [^]Type,
|
||||
// }
|
||||
|
||||
ArrayHeader :: struct ( $ Type : typeid ) {
|
||||
allocator : Allocator,
|
||||
backing : Allocator,
|
||||
capacity : u64,
|
||||
num : u64,
|
||||
data : [^]Type,
|
||||
@ -62,7 +62,7 @@ array_init_reserve :: proc
|
||||
if alloc_error != AllocatorError.None do return
|
||||
|
||||
result.header = cast( ^ArrayHeader(Type)) raw_mem;
|
||||
result.allocator = allocator
|
||||
result.backing = allocator
|
||||
result.capacity = capacity
|
||||
result.data = cast( [^]Type ) (cast( [^]ArrayHeader(Type)) result.header)[ 1:]
|
||||
return
|
||||
@ -201,13 +201,13 @@ array_fill :: proc( using self : Array( $ Type ), begin, end : u64, value : Type
|
||||
}
|
||||
|
||||
array_free :: proc( using self : Array( $ Type ) ) {
|
||||
free( data, allocator )
|
||||
free( data, backing )
|
||||
self.data = nil
|
||||
}
|
||||
|
||||
array_grow :: proc( using self : ^Array( $ Type ), min_capacity : u64 ) -> AllocatorError
|
||||
{
|
||||
profile(#procedure)
|
||||
// profile(#procedure)
|
||||
new_capacity := array_grow_formula( capacity )
|
||||
|
||||
if new_capacity < min_capacity {
|
||||
@ -269,13 +269,19 @@ array_set_capacity :: proc( self : ^Array( $ Type ), new_capacity : u64 ) -> All
|
||||
new_size := header_size + cast(int) new_capacity * size_of(Type)
|
||||
old_size := header_size + cast(int) self.capacity * size_of(Type)
|
||||
|
||||
new_mem, result_code := resize( self.header, old_size, new_size, allocator = self.allocator )
|
||||
// new_mem, result_code := resize( self.header, old_size, new_size, allocator = self.backing )
|
||||
new_mem, result_code := reisze_non_zeroed( byte_slice( self.header, old_size), new_size, mem.DEFAULT_ALIGNMENT, allocator = self.backing )
|
||||
|
||||
if result_code != AllocatorError.None {
|
||||
ensure( false, "Failed to allocate for new array capacity" )
|
||||
return result_code
|
||||
}
|
||||
if new_mem == nil {
|
||||
ensure(false, "new_mem is nil but no allocation error")
|
||||
return result_code
|
||||
}
|
||||
|
||||
self.header = cast( ^ArrayHeader(Type)) new_mem;
|
||||
self.header = cast( ^ArrayHeader(Type)) raw_data(new_mem);
|
||||
self.data = cast( [^]Type ) (cast( [^]ArrayHeader(Type)) self.header)[ 1:]
|
||||
self.capacity = new_capacity
|
||||
self.num = self.num
|
||||
|
@ -119,7 +119,7 @@ zpl_hmap_rehash :: proc( ht : ^ HMapZPL( $ Type ), new_num : u64 ) -> AllocatorE
|
||||
ensure( false, "ZPL HMAP IS REHASHING" )
|
||||
last_added_index : i64
|
||||
|
||||
new_ht, init_result := zpl_hmap_init_reserve( Type, ht.hashes.allocator, new_num )
|
||||
new_ht, init_result := zpl_hmap_init_reserve( Type, ht.hashes.backing, new_num )
|
||||
if init_result != AllocatorError.None {
|
||||
ensure( false, "New zpl_hmap failed to allocate" )
|
||||
return init_result
|
||||
|
@ -43,12 +43,6 @@ Pool_FreeBlock :: struct {
|
||||
|
||||
Pool_Check_Release_Object_Validity :: true
|
||||
|
||||
pool_allocator :: proc ( using self : Pool ) -> (allocator : Allocator) {
|
||||
allocator.procedure = pool_allocator_proc
|
||||
allocator.data = self.header
|
||||
return
|
||||
}
|
||||
|
||||
pool_init :: proc (
|
||||
block_size : uint,
|
||||
bucket_capacity : uint,
|
||||
@ -98,12 +92,12 @@ pool_allocate_buckets :: proc( using self : Pool, num_buckets : uint ) -> Alloca
|
||||
header_size := cast(uint) align_forward_int( size_of(PoolBucket), int(alignment))
|
||||
to_allocate := cast(int) (header_size + bucket_capacity * num_buckets)
|
||||
|
||||
bucket_memory, alloc_error := alloc( to_allocate, int(alignment), backing )
|
||||
bucket_memory, alloc_error := alloc_bytes_non_zeroed( to_allocate, int(alignment), backing )
|
||||
if alloc_error != .None {
|
||||
return alloc_error
|
||||
}
|
||||
|
||||
next_bucket_ptr := cast( [^]byte) bucket_memory
|
||||
next_bucket_ptr := cast( [^]byte) raw_data(bucket_memory)
|
||||
for index in 0 ..< num_buckets
|
||||
{
|
||||
bucket := cast( ^PoolBucket) next_bucket_ptr
|
||||
@ -151,6 +145,7 @@ pool_grab :: proc( using pool : Pool ) -> ( block : []byte, alloc_error : Alloca
|
||||
{
|
||||
alloc_error = pool_allocate_buckets( pool, 1 )
|
||||
if alloc_error != .None {
|
||||
ensure(false, "Failed to allocate bucket")
|
||||
return
|
||||
}
|
||||
pool.current_bucket = bucket_list.first
|
||||
@ -175,6 +170,7 @@ pool_grab :: proc( using pool : Pool ) -> ( block : []byte, alloc_error : Alloca
|
||||
{
|
||||
alloc_error := pool_allocate_buckets( pool, 1 )
|
||||
if alloc_error != .None {
|
||||
ensure(false, "Failed to allocate bucket")
|
||||
return
|
||||
}
|
||||
pool.current_bucket = pool.current_bucket.next
|
||||
@ -243,33 +239,3 @@ pool_validate_ownership :: proc( using self : Pool, block : [] byte ) -> b32
|
||||
|
||||
return within_bucket
|
||||
}
|
||||
|
||||
// This interface should really not be used for a pool allocator... But fk it its here.
|
||||
// TODO(Ed): Implement this eventaully..
|
||||
pool_allocator_proc :: proc(
|
||||
allocator_data : rawptr,
|
||||
mode : AllocatorMode,
|
||||
size : int,
|
||||
alignment : int,
|
||||
old_memory : rawptr,
|
||||
old_size : int,
|
||||
loc := #caller_location
|
||||
) -> ([]byte, AllocatorError)
|
||||
{
|
||||
switch mode
|
||||
{
|
||||
case .Alloc, .Alloc_Non_Zeroed:
|
||||
fallthrough
|
||||
case .Free:
|
||||
fallthrough
|
||||
case .Free_All:
|
||||
fallthrough
|
||||
case .Resize, .Resize_Non_Zeroed:
|
||||
fallthrough
|
||||
case .Query_Features:
|
||||
fallthrough
|
||||
case .Query_Info:
|
||||
fallthrough
|
||||
}
|
||||
return nil, AllocatorError.Mode_Not_Implemented
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ slab_init :: proc( policy : ^SlabPolicy, bucket_reserve_num : uint = 0, allocato
|
||||
|
||||
slab_init_pools :: proc ( using self : Slab, bucket_reserve_num : uint = 0 ) -> AllocatorError
|
||||
{
|
||||
profile(#procedure)
|
||||
for id in 0 ..< policy.idx {
|
||||
using size_class := policy.items[id]
|
||||
|
||||
|
@ -75,7 +75,7 @@ str_intern :: proc(
|
||||
{
|
||||
length := len(content)
|
||||
// str_mem, alloc_error := alloc( length, mem.DEFAULT_ALIGNMENT )
|
||||
str_mem, alloc_error := slab_alloc( cache.slab, uint(length), uint(mem.DEFAULT_ALIGNMENT) )
|
||||
str_mem, alloc_error := slab_alloc( cache.slab, uint(length), uint(mem.DEFAULT_ALIGNMENT), zero_memory = false )
|
||||
verify( alloc_error == .None, "String cache had a backing allocator error" )
|
||||
|
||||
// copy_non_overlapping( str_mem, raw_data(content), length )
|
||||
|
@ -100,13 +100,16 @@ varena_alloc :: proc( using self : ^VArena,
|
||||
|
||||
requested_size := size
|
||||
if requested_size == 0 {
|
||||
ensure(false, "Requested 0 size")
|
||||
return nil, .Invalid_Argument
|
||||
}
|
||||
// ensure( requested_size > page_size, "Requested less than a page size, going to allocate a page size")
|
||||
// requested_size = max(requested_size, page_size)
|
||||
|
||||
sync.mutex_guard( & mutex )
|
||||
|
||||
alignment_offset := uint(0)
|
||||
current_offset := cast(uintptr) reserve_start[ commit_used:]
|
||||
current_offset := uintptr(self.reserve_start) + uintptr(commit_used)
|
||||
mask := uintptr(alignment - 1)
|
||||
|
||||
if current_offset & mask != 0 {
|
||||
@ -140,10 +143,9 @@ varena_alloc :: proc( using self : ^VArena,
|
||||
}
|
||||
}
|
||||
|
||||
aligned_start := uintptr(self.commit_used + alignment_offset)
|
||||
data_ptr := rawptr(uintptr( reserve_start ) + aligned_start)
|
||||
data_ptr := rawptr(current_offset + uintptr(alignment_offset))
|
||||
data = byte_slice( data_ptr, int(requested_size) )
|
||||
commit_used += size_to_allocate
|
||||
self.commit_used += size_to_allocate
|
||||
alloc_error = .None
|
||||
|
||||
if zero_memory {
|
||||
@ -182,6 +184,8 @@ varena_allocator_proc :: proc(
|
||||
alignment := uint(alignment)
|
||||
old_size := uint(old_size)
|
||||
|
||||
page_size := uint(virtual_get_page_size())
|
||||
|
||||
switch mode
|
||||
{
|
||||
case .Alloc, .Alloc_Non_Zeroed:
|
||||
@ -195,31 +199,43 @@ varena_allocator_proc :: proc(
|
||||
|
||||
case .Resize, .Resize_Non_Zeroed:
|
||||
if old_memory == nil {
|
||||
ensure(false, "Resizing without old_memory?")
|
||||
return varena_alloc( arena, size, alignment, (mode != .Resize_Non_Zeroed), location )
|
||||
}
|
||||
|
||||
if size == old_size {
|
||||
ensure(false, "Requested resize when none needed")
|
||||
data = byte_slice( old_memory, old_size )
|
||||
return
|
||||
}
|
||||
|
||||
alignment_offset := uintptr(old_memory) & uintptr(alignment - 1)
|
||||
if alignment_offset == 0 && size < old_size {
|
||||
ensure(false, "Requested a shrink from a virtual arena")
|
||||
data = byte_slice( old_memory, size )
|
||||
return
|
||||
}
|
||||
|
||||
old_memory_offset := uintptr(old_memory) + uintptr(old_size)
|
||||
current_offset := uintptr(arena.reserve_start) + uintptr(arena.commit_used)
|
||||
|
||||
// if old_size < page_size {
|
||||
// // We're dealing with an allocation that requested less than the minimum allocated on vmem.
|
||||
// // Provide them more of their actual memory
|
||||
// data = byte_slice( old_memory, size )
|
||||
// return
|
||||
// }
|
||||
|
||||
verify( old_memory_offset == current_offset || arena.allow_any_reize,
|
||||
"Cannot resize existing allocation in vitual arena to a larger size unless it was the last allocated" )
|
||||
|
||||
if old_memory_offset == current_offset && arena.allow_any_reize
|
||||
if old_memory_offset != current_offset && arena.allow_any_reize
|
||||
{
|
||||
// Give it new memory and copy the old over. Old memory is unrecoverable until clear.
|
||||
new_region : []byte
|
||||
new_region, alloc_error = varena_alloc( arena, size, alignment, (mode != .Resize_Non_Zeroed), location )
|
||||
if new_region == nil || alloc_error != .None {
|
||||
ensure(false, "Failed to grab new region")
|
||||
data = byte_slice( old_memory, old_size )
|
||||
return
|
||||
}
|
||||
@ -232,6 +248,7 @@ varena_allocator_proc :: proc(
|
||||
new_region : []byte
|
||||
new_region, alloc_error = varena_alloc( arena, size - old_size, alignment, (mode != .Resize_Non_Zeroed), location )
|
||||
if new_region == nil || alloc_error != .None {
|
||||
ensure(false, "Failed to grab new region")
|
||||
data = byte_slice( old_memory, old_size )
|
||||
return
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ pws_parser_parse :: proc( text : string, allocator : Allocator ) -> ( PWS_ParseR
|
||||
nodes, alloc_error = array_init_reserve( PWS_AST, allocator, 8 )
|
||||
verify( alloc_error == nil, "Allocation failure creating nodes array")
|
||||
|
||||
lines, alloc_error = array_init_reserve( ^PWS_AST, allocator, 8 )
|
||||
parser.lines, alloc_error = array_init_reserve( ^PWS_AST, allocator, 8 )
|
||||
verify( alloc_error == nil, "Allocation failure creating line array")
|
||||
|
||||
//region Helper procs
|
||||
@ -301,12 +301,11 @@ pws_parser_parse :: proc( text : string, allocator : Allocator ) -> ( PWS_ParseR
|
||||
type = .Visible
|
||||
|
||||
case .New_Line:
|
||||
{
|
||||
eat_line()
|
||||
|
||||
alloc_error = array_append( & lines, prev_line )
|
||||
alloc_error = array_append( & parser.lines, prev_line )
|
||||
verify( alloc_error == nil, "Allocation failure appending node")
|
||||
}
|
||||
|
||||
case PWS_TokenType.End_Of_File:
|
||||
}
|
||||
|
||||
@ -357,7 +356,7 @@ pws_parser_parse :: proc( text : string, allocator : Allocator ) -> ( PWS_ParseR
|
||||
if line.first != nil {
|
||||
eat_line()
|
||||
|
||||
alloc_error = array_append( & lines, prev_line )
|
||||
alloc_error = array_append( & parser.lines, prev_line )
|
||||
verify( alloc_error == nil, "Allocation failure appending node")
|
||||
}
|
||||
|
||||
|
@ -238,8 +238,11 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
test_draggable()
|
||||
// test_text_box()
|
||||
|
||||
// Test Parenting
|
||||
|
||||
|
||||
// Whitespace AST test
|
||||
when true
|
||||
when false
|
||||
{
|
||||
profile("Whitespace AST test")
|
||||
|
||||
@ -267,7 +270,7 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
alloc_error : AllocatorError; success : bool
|
||||
// debug.lorem_content, success = os.read_entire_file( debug.path_lorem, frame_allocator() )
|
||||
|
||||
// debug.lorem_parse, alloc_error = pws_parser_parse( transmute(string) debug.lorem_content, frame_allocator() )
|
||||
// debug.lorem_parse, alloc_error = pws_parser_parse( transmute(string) debug.lorem_content, frame_slab_allocator() )
|
||||
// verify( alloc_error == .None, "Faield to parse due to allocation failure" )
|
||||
|
||||
text_space := str_intern( " " )
|
||||
@ -275,7 +278,7 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
|
||||
// index := 0
|
||||
widgets : Array(UI_Widget)
|
||||
widgets, alloc_error = array_init( UI_Widget, frame_allocator() )
|
||||
widgets, alloc_error = array_init( UI_Widget, frame_slab_allocator() )
|
||||
widgets_ptr := & widgets
|
||||
|
||||
label_id := 0
|
||||
|
@ -319,8 +319,8 @@ ui_reload :: proc( ui : ^ UI_State, cache_allocator : Allocator )
|
||||
{
|
||||
// We need to repopulate Allocator references
|
||||
for cache in & ui.caches {
|
||||
cache.entries.allocator = cache_allocator
|
||||
cache.hashes.allocator = cache_allocator
|
||||
cache.entries.backing = cache_allocator
|
||||
cache.hashes.backing = cache_allocator
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user