Added maximum bytes allocated in debug allocator, as well as peak memory usage

This commit is contained in:
Alexandros Naskos 2020-06-09 16:39:00 +03:00
parent aa0e3e3736
commit c2f8537d7b
3 changed files with 30 additions and 4 deletions

View File

@ -148,6 +148,13 @@ pub fn build(b: *std.build.Builder) !void {
b.option(bool, "allocation_info", "Enable use of debugging allocator and info logging.") orelse false, b.option(bool, "allocation_info", "Enable use of debugging allocator and info logging.") orelse false,
); );
const max_bytes_str = b.option([]const u8, "max_bytes_allocated", "Maximum amount of bytes to allocate before we exit. Zero for unlimited allocations. Only takes effect when allocation_info=true") orelse "0";
exe.addBuildOption(
usize,
"max_bytes_allocated",
try std.fmt.parseInt(usize, max_bytes_str, 10),
);
exe.addPackage(.{ .name = "known-folders", .path = "src/known-folders/known-folders.zig" }); exe.addPackage(.{ .name = "known-folders", .path = "src/known-folders/known-folders.zig" });
exe.setTarget(target); exe.setTarget(target);

View File

@ -35,9 +35,15 @@ pub const AllocationInfo = struct {
deallocation_count: usize = 0, deallocation_count: usize = 0,
deallocation_total: usize = 0, deallocation_total: usize = 0,
peak_allocated: usize = 0,
reallocation_stats: Stats = Stats{}, reallocation_stats: Stats = Stats{},
shrink_stats: Stats = Stats{}, shrink_stats: Stats = Stats{},
fn currentlyAllocated(self: AllocationInfo) usize {
return self.allocation_stats.total + self.reallocation_stats.total - self.deallocation_total - self.shrink_stats.total;
}
pub fn format( pub fn format(
self: AllocationInfo, self: AllocationInfo,
comptime fmt: []const u8, comptime fmt: []const u8,
@ -51,7 +57,7 @@ pub const AllocationInfo = struct {
out_stream, out_stream,
\\------------------------------------------ Allocation info ------------------------------------------ \\------------------------------------------ Allocation info ------------------------------------------
\\{} total allocations (total: {d:.2} MB, mean: {d:.2} MB, std. dev: {d:.2} MB), {} deallocations \\{} total allocations (total: {d:.2} MB, mean: {d:.2} MB, std. dev: {d:.2} MB), {} deallocations
\\{} current allocations ({d:.2} MB) \\{} current allocations ({d:.2} MB), peak mem usage: {d:.2} MB
\\{} reallocations (total: {d:.2} MB, mean: {d:.2} MB, std. dev: {d:.2} MB) \\{} reallocations (total: {d:.2} MB, mean: {d:.2} MB, std. dev: {d:.2} MB)
\\{} shrinks (total: {d:.2} MB, mean: {d:.2} MB, std. dev: {d:.2} MB) \\{} shrinks (total: {d:.2} MB, mean: {d:.2} MB, std. dev: {d:.2} MB)
\\----------------------------------------------------------------------------------------------------- \\-----------------------------------------------------------------------------------------------------
@ -63,7 +69,8 @@ pub const AllocationInfo = struct {
toMB(self.allocation_stats.stdDev()), toMB(self.allocation_stats.stdDev()),
self.deallocation_count, self.deallocation_count,
self.allocation_stats.count - self.deallocation_count, self.allocation_stats.count - self.deallocation_count,
toMB(self.allocation_stats.total + self.reallocation_stats.total - self.deallocation_total - self.shrink_stats.total), toMB(self.currentlyAllocated()),
toMB(self.peak_allocated),
self.reallocation_stats.count, self.reallocation_stats.count,
toMB(self.reallocation_stats.total), toMB(self.reallocation_stats.total),
toMB(self.reallocation_stats.mean), toMB(self.reallocation_stats.mean),
@ -79,14 +86,16 @@ pub const AllocationInfo = struct {
base_allocator: *std.mem.Allocator, base_allocator: *std.mem.Allocator,
info: AllocationInfo, info: AllocationInfo,
max_bytes: usize,
// Interface implementation // Interface implementation
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
pub fn init(base_allocator: *std.mem.Allocator) DebugAllocator { pub fn init(base_allocator: *std.mem.Allocator, max_bytes: usize) DebugAllocator {
return .{ return .{
.base_allocator = base_allocator, .base_allocator = base_allocator,
.info = .{}, .info = .{},
.max_bytes = max_bytes,
.allocator = .{ .allocator = .{
.reallocFn = realloc, .reallocFn = realloc,
.shrinkFn = shrink, .shrinkFn = shrink,
@ -104,6 +113,16 @@ fn realloc(allocator: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_siz
} else if (new_size < old_mem.len) { } else if (new_size < old_mem.len) {
self.info.shrink_stats.addSample(old_mem.len - new_size); self.info.shrink_stats.addSample(old_mem.len - new_size);
} }
const curr_allocs = self.info.currentlyAllocated();
if (self.max_bytes != 0 and curr_allocs >= self.max_bytes) {
std.debug.warn("Exceeded maximum bytes {}, exiting.\n", .{self.max_bytes});
std.process.exit(1);
}
if (curr_allocs > self.info.peak_allocated) {
self.info.peak_allocated = curr_allocs;
}
return data; return data;
} }

View File

@ -997,7 +997,7 @@ pub fn main() anyerror!void {
if (build_options.allocation_info) { if (build_options.allocation_info) {
// TODO: Use a better debugging allocator, track size in bytes, memory reserved etc.. // TODO: Use a better debugging allocator, track size in bytes, memory reserved etc..
// Initialize the leak counting allocator. // Initialize the leak counting allocator.
debug_alloc_state = DebugAllocator.init(allocator); debug_alloc_state = DebugAllocator.init(allocator, build_options.max_bytes_allocated);
allocator = &debug_alloc_state.allocator; allocator = &debug_alloc_state.allocator;
} }