From 6cffb888eae8ebfc869ff2fdb715d1260a480fc8 Mon Sep 17 00:00:00 2001 From: m0tholith <48518572+m0tholith@users.noreply.github.com> Date: Sun, 25 Jan 2026 18:11:46 +0300 Subject: [PATCH] Add maximum memory usage tracking to tracking allocator (#2772) Co-authored-by: Christoffer Lerno --- lib/std/core/allocators/tracking_allocator.c3 | 15 +++++++++++++++ releasenotes.md | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/std/core/allocators/tracking_allocator.c3 b/lib/std/core/allocators/tracking_allocator.c3 index 00ce4d90a..b3049ffa3 100644 --- a/lib/std/core/allocators/tracking_allocator.c3 +++ b/lib/std/core/allocators/tracking_allocator.c3 @@ -28,6 +28,8 @@ struct TrackingAllocator (Allocator) AllocMap map; usz mem_total; usz allocs_total; + usz usage; + usz max_usage; } <* @@ -70,6 +72,11 @@ fn usz TrackingAllocator.total_allocated(&self) => self.mem_total; *> fn usz TrackingAllocator.total_allocation_count(&self) => self.allocs_total; +<* + @return "the maximum amount of memory allocated" +*> +fn usz TrackingAllocator.max_allocated(&self) => self.max_usage; + fn Allocation[] TrackingAllocator.allocations_tlist(&self, Allocator allocator) { return self.map.tvalues(); @@ -88,27 +95,34 @@ fn void*? TrackingAllocator.acquire(&self, usz size, AllocInitType init_type, us backtrace::capture_current(&bt); self.map.set((uptr)data, { data, size, bt }); self.mem_total += size; + self.usage += size; + if (self.usage > self.max_usage) self.max_usage = self.usage; return data; } fn void*? TrackingAllocator.resize(&self, void* old_pointer, usz size, usz alignment) @dynamic { void* data = self.inner_allocator.resize(old_pointer, size, alignment)!; + self.usage -= self.map[(uptr)old_pointer]!!.size; self.map.remove((uptr)old_pointer); void*[MAX_BACKTRACE] bt; backtrace::capture_current(&bt); self.map.set((uptr)data, { data, size, bt }); self.mem_total += size; + self.usage += size; + if (self.usage > self.max_usage) self.max_usage = self.usage; self.allocs_total++; return data; } fn void TrackingAllocator.release(&self, void* old_pointer, bool is_aligned) @dynamic { + usz? old_size = self.map[(uptr)old_pointer].size; if (catch self.map.remove((uptr)old_pointer)) { unreachable("Attempt to release untracked pointer %p, this is likely a bug.", old_pointer); } + self.usage -= old_size!!; self.inner_allocator.release(old_pointer, is_aligned); } @@ -177,6 +191,7 @@ fn void? TrackingAllocator.fprint_report(&self, OutStream out) => @pool() io::fprintfn(out, "- Total current allocations: %d", entries)!; io::fprintfn(out, "- Total allocations (freed and retained): %d", self.allocs_total)!; io::fprintfn(out, "- Total allocated memory (freed and retained): %d", self.mem_total)!; + io::fprintfn(out, "- Maximum memory usage: %d", self.max_usage)!; if (leaks) { io::fprintn(out)!; diff --git a/releasenotes.md b/releasenotes.md index 8b13d91de..c3067ff59 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -23,7 +23,6 @@ - Make `foo.$abc` implicitly mean `foo.eval("$abc")`. - Deprecating multi-level array length inference. `int[*][*]` is deprecated and will be removed 0.8.0. - Combining argument-less initialization with argument init for bitstructs is now allowed e.g. `{ .b, .c = 123 }`. -- Bug when initializing an inferred array with deep structure using designated init #2826 ### Fixes - Regression with npot vector in struct triggering an assert #2219. @@ -130,6 +129,7 @@ - Store of zero in lowering did not properly handle optionals in some cases #2837 - Bitstruct accidentally allowed other arrays than char arrays #2836 - Bitstruct as substruct fails to properly work with designated initializers. #2827 +- Bug when initializing an inferred array with deep structure using designated init #2826 ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. @@ -158,6 +158,7 @@ - HashSet.len() now returns usz instead of int. #2740 - Add `mem::store` and `mem::load` which may combine both aligned and volatile operations. - Deprecated `EMPTY_MACRO_SLOT` and its related uses, in favor of `optional_param = ...` named macro arguments. #2805 +- Add tracking of peak memory usage in the tracking allocator. ## 0.7.8 Change list