mem tracker updates

This commit is contained in:
Edward R. Gonzalez 2024-06-20 15:36:47 -04:00
parent f9820457d1
commit c405c47e6c
7 changed files with 63 additions and 41 deletions

View File

@ -57,7 +57,8 @@ hmap_chained_init :: proc( $HMapChainedType : typeid/HMapChained($Type), lookup_
pool_bucket_cap : uint = 1 * Kilo,
pool_bucket_reserve_num : uint = 0,
pool_alignment : uint = mem.DEFAULT_ALIGNMENT,
dbg_name : string = ""
dbg_name : string = "",
enable_mem_tracking : b32 = false,
) -> (table : HMapChained(Type), error : AllocatorError)
{
header_size := size_of(HMapChainedHeader(Type))
@ -75,7 +76,8 @@ hmap_chained_init :: proc( $HMapChainedType : typeid/HMapChained($Type), lookup_
bucket_reserve_num = pool_bucket_reserve_num,
alignment = pool_alignment,
allocator = allocator,
dbg_name = str_intern(str_fmt("%v: pool", dbg_name)).str
dbg_name = str_intern(str_fmt("%v: pool", dbg_name)).str,
enable_mem_tracking = enable_mem_tracking,
)
data := transmute([^] ^HMapChainedSlot(Type)) (transmute( [^]HMapChainedHeader(Type)) table.header)[1:]
table.lookup = slice_ptr( data, int(lookup_capacity) )

View File

@ -13,11 +13,12 @@ MemoryTrackerEntry :: struct {
}
MemoryTracker :: struct {
parent : ^MemoryTracker,
name : string,
entries : Array(MemoryTrackerEntry),
}
Track_Memory :: false
Track_Memory :: true
memtracker_clear :: proc ( tracker : MemoryTracker ) {
when ! Track_Memory {
@ -69,17 +70,17 @@ memtracker_register :: proc( tracker : ^MemoryTracker, new_entry : MemoryTracker
if (entry.end < new_entry.start)
{
msg := str_fmt("Memory tracker(%v) detected a collision:\nold_entry: %v\nnew_entry: %v", tracker.name, entry, new_entry)
msg := str_fmt("Detected a collision:\nold_entry: %v -> %v\nnew_entry: %v -> %v | %v", entry.start, entry.end, new_entry.start, new_entry.end, tracker.name )
ensure( false, msg )
memtracker_dump_entries(tracker ^)
}
array_append_at( & tracker.entries, new_entry, idx )
logf("%v : Registered: %v", tracker.name, new_entry)
logf("Registered: %v -> %v | %v", new_entry.start, new_entry.end, tracker.name)
return
}
array_append( & tracker.entries, new_entry )
logf("%v : Registered: %v", tracker.name, new_entry)
logf("Registered: %v -> %v | %v", new_entry.start, new_entry.end, tracker.name )
}
memtracker_register_auto_name :: proc( tracker : ^MemoryTracker, start, end : rawptr )
@ -117,17 +118,17 @@ memtracker_unregister :: proc( tracker : MemoryTracker, to_remove : MemoryTracke
entry := & entries[idx]
if entry.start == to_remove.start {
if (entry.end == to_remove.end || to_remove.end == nil) {
logf("%v: Unregistered: %v", tracker.name, to_remove);
logf("Unregistered: %v -> %v | %v", to_remove.start, to_remove.end, tracker.name );
array_remove_at(tracker.entries, idx)
return
}
ensure(false, str_fmt("%v: Found an entry with the same start address but end address was different:\nentry : %v\nto_remove: %v", tracker.name, entry, to_remove))
ensure(false, str_fmt("Found an entry with the same start address but end address was different:\nentry : %v -> %v\nto_remove: %v -> %v | %v", entry.start, entry.end, to_remove.start, to_remove.end, tracker.name ))
memtracker_dump_entries(tracker)
}
}
ensure(false, str_fmt("%v: Attempted to unregister an entry that was not tracked: %v", tracker.name, to_remove))
ensure(false, str_fmt("Attempted to unregister an entry that was not tracked: %v -> %v | %v", to_remove.start, to_remove.end, tracker.name))
memtracker_dump_entries(tracker)
}
@ -150,7 +151,7 @@ memtracker_check_for_collisions :: proc ( tracker : MemoryTracker )
collided := left.start > right.start || left.end > right.end
if collided {
msg := str_fmt("%v: Memory tracker detected a collision:\nleft: %v\nright: %v", tracker.name, left, right)
msg := str_fmt("Memory tracker detected a collision:\nleft: %v\nright: %v | %v", left, right, tracker.name )
memtracker_dump_entries(tracker)
}
}
@ -165,6 +166,6 @@ memtracker_dump_entries :: proc( tracker : MemoryTracker )
log( "Dumping Memory Tracker:")
for idx in 0 ..< tracker.entries.num {
entry := & tracker.entries.data[idx]
logf("%v", entry)
logf("%v -> %v", entry.start, entry.end)
}
}

View File

@ -25,7 +25,8 @@ Pool :: struct {
PoolHeader :: struct {
backing : Allocator,
dbg_name : string,
tracker : MemoryTracker,
tracker : MemoryTracker,
// bucket_tracker : MemoryTracker,
zero_bucket : b32,
block_size : uint,
@ -57,6 +58,7 @@ pool_init :: proc (
alignment : uint = mem.DEFAULT_ALIGNMENT,
allocator : Allocator = context.allocator,
dbg_name : string = "",
enable_mem_tracking : b32 = false,
) -> ( pool : Pool, alloc_error : AllocatorError )
{
header_size := align_forward_int( size_of(PoolHeader), int(alignment) )
@ -76,8 +78,9 @@ pool_init :: proc (
pool.bucket_capacity = bucket_capacity
pool.alignment = alignment
when ODIN_DEBUG {
if Track_Memory && enable_mem_tracking {
memtracker_init( & pool.tracker, allocator, Kilobyte * 96, dbg_name )
// memtracker_init( & pool.bucket_tracker, allocator, Kilobyte * 96, dbg_name )
}
if bucket_reserve_num > 0 {
@ -104,8 +107,9 @@ pool_destroy :: proc ( using self : Pool )
free( self.header, backing )
when ODIN_DEBUG {
if Track_Memory && self.tracker.entries.header != nil {
memtracker_clear( self.tracker )
// memtracker_clear( self.bucket_tracker )
}
}
@ -133,6 +137,10 @@ pool_allocate_buckets :: proc( pool : Pool, num_buckets : uint ) -> AllocatorErr
}
pool_validate( pool )
// if Track_Memory && pool.tracker.entries.header != nil {
// memtracker_register_auto_name_slice( & pool.bucket_tracker, bucket_memory)
// }
// log(str_fmt_tmp("Bucket memory size: %d bytes, without header: %d", len(bucket_memory), len(bucket_memory) - int(header_size)))
if alloc_error != .None {
@ -195,7 +203,7 @@ pool_grab :: proc( pool : Pool, zero_memory := false ) -> ( block : []byte, allo
slice.zero(block)
}
when ODIN_DEBUG {
if Track_Memory && pool.tracker.entries.header != nil {
memtracker_register_auto_name_slice( & pool.tracker, block)
}
return
@ -258,7 +266,7 @@ pool_grab :: proc( pool : Pool, zero_memory := false ) -> ( block : []byte, allo
// log( str_fmt_tmp("Zeroed memory - Range(%p to %p)", block_ptr, cast(rawptr) (uintptr(block_ptr) + uintptr(pool.block_size))))
}
when ODIN_DEBUG {
if Track_Memory && pool.tracker.entries.header != nil {
memtracker_register_auto_name_slice( & pool.tracker, block)
}
return
@ -289,7 +297,7 @@ pool_release :: proc( self : Pool, block : []byte, loc := #caller_location )
start := new_free_block
end := transmute(rawptr) (uintptr(new_free_block) + uintptr(self.block_size) - 1)
when ODIN_DEBUG {
if Track_Memory && self.tracker.entries.header != nil {
memtracker_unregister( self.tracker, { start, end } )
}
}

View File

@ -27,6 +27,7 @@ package grime
import "base:runtime"
import "core:mem"
import "core:slice"
import "core:strings"
SlabSizeClass :: struct {
bucket_capacity : uint,
@ -55,7 +56,12 @@ slab_allocator :: proc( slab : Slab ) -> ( allocator : Allocator ) {
return
}
slab_init :: proc( policy : ^SlabPolicy, bucket_reserve_num : uint = 0, allocator : Allocator = context.allocator, dbg_name : string = "", should_zero_buckets : b32 = false ) -> ( slab : Slab, alloc_error : AllocatorError )
slab_init :: proc( policy : ^SlabPolicy, bucket_reserve_num : uint = 0,
allocator : Allocator = context.allocator,
dbg_name : string = "",
should_zero_buckets : b32 = false,
enable_mem_tracking : b32 = false,
) -> ( slab : Slab, alloc_error : AllocatorError )
{
header_size :: size_of( SlabHeader )
@ -66,10 +72,10 @@ slab_init :: proc( policy : ^SlabPolicy, bucket_reserve_num : uint = 0, allocato
slab.header = cast( ^SlabHeader) raw_mem
slab.backing = allocator
slab.dbg_name = dbg_name
when ODIN_DEBUG {
if Track_Memory && enable_mem_tracking {
memtracker_init( & slab.tracker, allocator, Kilobyte * 256, dbg_name )
}
alloc_error = slab_init_pools( slab, policy, bucket_reserve_num, should_zero_buckets )
alloc_error = slab_init_pools( slab, policy, bucket_reserve_num, should_zero_buckets )
return
}
@ -80,8 +86,12 @@ slab_init_pools :: proc ( using self : Slab, policy : ^SlabPolicy, bucket_reserv
for id in 0 ..< policy.idx {
using size_class := policy.items[id]
pool_dbg_name := str_fmt("%v pool[%v]", dbg_name, block_size, allocator = backing)
pool, alloc_error := pool_init( should_zero_buckets, block_size, bucket_capacity, bucket_reserve_num, block_alignment, backing, pool_dbg_name )
name_temp := str_fmt_tmp("%v pool[%v]", dbg_name, block_size)
pool_dbg_name, error := strings.clone( name_temp, allocator = backing )
pool, alloc_error := pool_init( should_zero_buckets, block_size, bucket_capacity, bucket_reserve_num, block_alignment, backing,
pool_dbg_name,
enable_mem_tracking = Track_Memory && tracker.entries.header != nil
)
if alloc_error != .None do return alloc_error
push( & self.pools, pool )
@ -107,7 +117,7 @@ slab_destroy :: proc( using self : Slab )
}
free( self.header, backing )
when ODIN_DEBUG {
if Track_Memory && self.tracker.entries.header != nil {
memtracker_clear(tracker)
}
}
@ -148,7 +158,7 @@ slab_alloc :: proc( self : Slab,
slice.zero(data)
}
when ODIN_DEBUG {
if Track_Memory && self.tracker.entries.header != nil {
memtracker_register_auto_name( & self.tracker, raw_data(block), & block[ len(block) - 1 ] )
}
return
@ -165,7 +175,7 @@ slab_free :: proc( using self : Slab, data : []byte, loc := #caller_location )
start := raw_data(data)
end := ptr_offset(start, pool.block_size - 1)
when ODIN_DEBUG {
if Track_Memory && self.tracker.entries.header != nil {
memtracker_unregister( self.tracker, { start, end } )
}
@ -255,13 +265,13 @@ slab_resize :: proc( using self : Slab,
start := raw_data( data )
end := rawptr(uintptr(start) + uintptr(pool_old.block_size) - 1)
when ODIN_DEBUG {
if Track_Memory && self.tracker.entries.header != nil {
memtracker_unregister( self.tracker, { start, end } )
}
}
new_data = new_block[ :new_size]
when ODIN_DEBUG {
if Track_Memory && self.tracker.entries.header != nil {
memtracker_register_auto_name( & self.tracker, raw_data(new_block), & new_block[ len(new_block) - 1 ] )
}
return
@ -273,7 +283,7 @@ slab_reset :: proc( slab : Slab )
pool := slab.pools.items[id]
pool_reset( pool )
}
when ODIN_DEBUG {
when Track_Memory {
memtracker_clear(slab.tracker)
}
}

View File

@ -29,7 +29,7 @@ VArena :: struct {
dbg_name : string,
commit_used : uint,
growth_policy : VArena_GrowthPolicyProc,
allow_any_reize : b32,
allow_any_resize : b32,
mutex : sync.Mutex,
}
@ -61,7 +61,7 @@ varena_allocator :: proc( arena : ^VArena ) -> ( allocator : Allocator ) {
// Default growth_policy is nil
varena_init :: proc( base_address : uintptr, to_reserve, to_commit : uint,
growth_policy : VArena_GrowthPolicyProc, allow_any_reize : b32 = false, dbg_name : string
growth_policy : VArena_GrowthPolicyProc, allow_any_resize : b32 = false, dbg_name : string, enable_mem_tracking : b32 = false,
) -> ( arena : VArena, alloc_error : AllocatorError)
{
page_size := uint(virtual_get_page_size())
@ -86,9 +86,9 @@ varena_init :: proc( base_address : uintptr, to_reserve, to_commit : uint,
else {
arena.growth_policy = growth_policy
}
arena.allow_any_reize = allow_any_reize
arena.allow_any_resize = allow_any_resize
when ODIN_DEBUG {
if Track_Memory && enable_mem_tracking {
memtracker_init( & arena.tracker, runtime.heap_allocator(), Kilobyte * 128, dbg_name )
}
return
@ -165,7 +165,7 @@ varena_alloc :: proc( using self : ^VArena,
mem_zero( data_ptr, int(requested_size) )
}
when ODIN_DEBUG {
if Track_Memory && self.tracker.entries.header != nil {
memtracker_register_auto_name( & tracker, & data[0], & data[len(data) - 1] )
}
return
@ -176,7 +176,7 @@ varena_free_all :: proc( using self : ^VArena )
sync.mutex_guard( & mutex )
commit_used = 0
when ODIN_DEBUG && Track_Memory {
if Track_Memory && self.tracker.entries.header != nil {
array_clear(tracker.entries)
}
}
@ -251,13 +251,13 @@ varena_allocator_proc :: proc(
}
}
verify( old_memory_offset == current_offset || arena.allow_any_reize,
verify( old_memory_offset == current_offset || arena.allow_any_resize,
"Cannot resize existing allocation in vitual arena to a larger size unless it was the last allocated" )
log_backing : [Kilobyte * 16]byte
backing_slice := byte_slice( & log_backing[0], len(log_backing))
if old_memory_offset != current_offset && arena.allow_any_reize
if old_memory_offset != current_offset && arena.allow_any_resize
{
// Give it new memory and copy the old over. Old memory is unrecoverable until clear.
new_region : []byte
@ -266,7 +266,7 @@ varena_allocator_proc :: proc(
ensure(false, "Failed to grab new region")
data = byte_slice( old_memory, old_size )
when ODIN_DEBUG {
if Track_Memory && arena.tracker.entries.header != nil {
memtracker_register_auto_name( & arena.tracker, & data[0], & data[len(data) - 1] )
}
return
@ -276,7 +276,7 @@ varena_allocator_proc :: proc(
data = new_region
// log( str_fmt_tmp("varena resize (new): old: %p %v new: %p %v", old_memory, old_size, (& data[0]), size))
when ODIN_DEBUG {
when Track_Memory {
memtracker_register_auto_name( & arena.tracker, & data[0], & data[len(data) - 1] )
}
return
@ -293,7 +293,7 @@ varena_allocator_proc :: proc(
data = byte_slice( old_memory, size )
// log( str_fmt_tmp("varena resize (expanded): old: %p %v new: %p %v", old_memory, old_size, (& data[0]), size))
when ODIN_DEBUG {
if Track_Memory && arena.tracker.entries.header != nil {
memtracker_register_auto_name( & arena.tracker, & data[0], & data[len(data) - 1] )
}
return

View File

@ -129,7 +129,8 @@ setup_memory :: proc( profiler : ^SpallProfiler ) -> ClientMemory
sectr.Memory_Commit_Initial_Persistent,
growth_policy = nil,
allow_any_resize = false,
dbg_name = "persistent" )
dbg_name = "persistent",
enable_mem_tracking = true )
verify( alloc_error == .None, "Failed to allocate persistent virtual arena for the sectr module")
frame, alloc_error = varena_init(

View File

@ -92,7 +92,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
// push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment })
alloc_error : AllocatorError
persistent_slab, alloc_error = slab_init( policy_ptr, allocator = persistent_allocator(), dbg_name = Persistent_Slab_DBG_Name )
persistent_slab, alloc_error = slab_init( policy_ptr, allocator = persistent_allocator(), dbg_name = Persistent_Slab_DBG_Name, enable_mem_tracking = true )
verify( alloc_error == .None, "Failed to allocate the persistent slab" )
transient_slab, alloc_error = slab_init( & default_slab_policy, allocator = transient_allocator(), dbg_name = Transient_Slab_DBG_Name )