mem tracker updates
This commit is contained in:
		| @@ -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) ) | ||||
|   | ||||
| @@ -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) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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 } ) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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 ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user