diff --git a/examples/basic.zig b/examples/basic.zig index c5e1780..7c3fb6f 100644 --- a/examples/basic.zig +++ b/examples/basic.zig @@ -39,7 +39,6 @@ test "bench test basic" { }); const sysinfo = try bench.getSystemInfo(); - defer sysinfo.deinit(); try std.fmt.format(stdout, "\n{}\n", .{sysinfo}); const results = try bench.run(); diff --git a/util/os/linux.zig b/util/os/linux.zig index 84d3177..d95b40d 100644 --- a/util/os/linux.zig +++ b/util/os/linux.zig @@ -3,49 +3,56 @@ const fs = std.fs; const mem = std.mem; const log = std.log.scoped(.zbench_platform_linux); -pub fn getCpuName(allocator: mem.Allocator) ![]const u8 { +pub fn getCpuName(allocator: std.mem.Allocator) ![]const u8 { const file = try fs.cwd().openFile("/proc/cpuinfo", .{}); defer file.close(); - var buf: [128]u8 = undefined; - _ = try file.read(&buf); + const buf = try allocator.alloc(u8, 1024); + _ = try file.read(buf); - const start = if (mem.indexOf(u8, &buf, "model name")) |pos| pos + 13 else 0; - const end = if (mem.indexOfScalar(u8, buf[start..], '\n')) |pos| start + pos else 0; + const needle = "model name"; + const start = if (mem.indexOf(u8, buf, needle)) |pos| + pos + needle.len + 3 + else + return error.CouldNotFindCpuName; - if ((start == 0 and end == 0) or (start > end)) { + const len = if (mem.indexOfScalar(u8, buf[start..], '\n')) |pos| + pos + else return error.CouldNotFindCpuName; - } - return allocator.dupe(u8, buf[start..end]); + return buf[start..][0..len]; } -pub fn getCpuCores() !u32 { +pub fn getCpuCores(allocator: std.mem.Allocator) !u32 { const file = try fs.cwd().openFile("/proc/cpuinfo", .{}); defer file.close(); - var buf: [1024]u8 = undefined; - _ = try file.read(&buf); + const buf = try allocator.alloc(u8, 1024); + _ = try file.read(buf); - var token_iterator = std.mem.tokenizeSequence(u8, &buf, "\n"); + var token_iterator = std.mem.tokenizeSequence(u8, buf, "\n"); while (token_iterator.next()) |line| { if (std.mem.startsWith(u8, line, "cpu cores")) { const start = if (mem.indexOf(u8, line, ":")) |pos| pos + 2 else 0; - return try std.fmt.parseInt(u32, line[start..], 10); + return std.fmt.parseInt(u32, line[start..], 10) catch |err| { + log.err("Error parsing total memory size: {}\n", .{err}); + return err; + }; } } return error.CouldNotFindNumCores; } -pub fn getTotalMemory() !u64 { +pub fn getTotalMemory(allocator: std.mem.Allocator) !u64 { const file = try std.fs.cwd().openFile("/proc/meminfo", .{}); defer file.close(); - var buf: [128]u8 = undefined; - _ = try file.read(&buf); + const buf: []u8 = try allocator.alloc(u8, 1024); + _ = try file.read(buf); - var token_iterator = std.mem.tokenizeSequence(u8, &buf, "\n"); + var token_iterator = std.mem.tokenizeSequence(u8, buf, "\n"); while (token_iterator.next()) |line| { if (std.mem.startsWith(u8, line, "MemTotal:")) { // Extract the numeric value from the line diff --git a/util/os/osx.zig b/util/os/osx.zig index 14e12ce..7eea2e2 100644 --- a/util/os/osx.zig +++ b/util/os/osx.zig @@ -6,21 +6,16 @@ pub fn getCpuName(allocator: std.mem.Allocator) ![]const u8 { } pub fn getCpuCores(allocator: std.mem.Allocator) !u32 { - const coresString = try exec(allocator, &.{ "sysctl", "-n", "hw.physicalcpu" }); - defer allocator.free(coresString); - - return std.fmt.parseInt(u32, coresString, 10) catch |err| { + const str = try exec(allocator, &.{ "sysctl", "-n", "hw.physicalcpu" }); + return std.fmt.parseInt(u32, str, 10) catch |err| { log.err("Error parsing CPU cores count: {}\n", .{err}); return err; }; } pub fn getTotalMemory(allocator: std.mem.Allocator) !u64 { - const memSizeString = try exec(allocator, &.{ "sysctl", "-n", "hw.memsize" }); - defer allocator.free(memSizeString); - - // Parse the string to a 64-bit unsigned integer - return std.fmt.parseInt(u64, memSizeString, 10) catch |err| { + const str = try exec(allocator, &.{ "sysctl", "-n", "hw.memsize" }); + return std.fmt.parseInt(u64, str, 10) catch |err| { log.err("Error parsing total memory size: {}\n", .{err}); return err; }; diff --git a/util/platform.zig b/util/platform.zig index 5c59fa9..0506253 100644 --- a/util/platform.zig +++ b/util/platform.zig @@ -7,19 +7,16 @@ const lnx = @import("os/linux.zig"); const mac = @import("os/osx.zig"); const win = @import("os/windows.zig"); +var cpu_name_buffer: [128]u8 = undefined; +var osinfo: ?OsInfo = null; + pub const OsInfo = struct { - allocator: std.mem.Allocator, platform: []const u8, cpu: []const u8, cpu_cores: u32, - memory_total: []const u8, + memory_total: u64, // ... other system information - pub fn deinit(self: OsInfo) void { - self.allocator.free(self.cpu); - self.allocator.free(self.memory_total); - } - pub fn format( info: OsInfo, comptime _: []const u8, @@ -30,60 +27,71 @@ pub const OsInfo = struct { \\ Operating System: {s} \\ CPU: {s} \\ CPU Cores: {d} - \\ Total Memory: {s} + \\ Total Memory: {d:.3} \\ , .{ info.platform, info.cpu, info.cpu_cores, - info.memory_total, + std.fmt.fmtIntSizeBin(info.memory_total), }); } }; const platform = @tagName(builtin.os.tag) ++ " " ++ @tagName(builtin.cpu.arch); -pub fn getSystemInfo(allocator: std.mem.Allocator) !OsInfo { - return switch (builtin.os.tag) { - .linux => try linux(allocator), - .macos => try macos(allocator), - .windows => try windows(allocator), - else => error.UnsupportedOs, +pub fn getSystemInfo() !OsInfo { + if (osinfo) |x| return x; + osinfo = OsInfo{ + .platform = platform, + .cpu = try getCpuName(), + .cpu_cores = try getCpuCores(), + .memory_total = try getTotalMemory(), }; + return osinfo.?; } -pub fn linux(allocator: std.mem.Allocator) !OsInfo { - const memory = try lnx.getTotalMemory(); - - return OsInfo{ - .allocator = allocator, - .platform = platform, - .cpu = try lnx.getCpuName(allocator), - .cpu_cores = try lnx.getCpuCores(), - .memory_total = try format.memorySize(memory, allocator), +fn getCpuName() ![]const u8 { + var scratch: [4096]u8 = undefined; + var fbs = std.heap.FixedBufferAllocator.init(&scratch); + const cpu = switch (builtin.os.tag) { + .linux => try lnx.getCpuName(fbs.allocator()), + .macos => try mac.getCpuName(fbs.allocator()), + .windows => try win.getCpuName(fbs.allocator()), + else => error.UnsupportedOs, }; + const len: usize = @min(cpu_name_buffer.len, cpu.len); + std.mem.copyForwards(u8, cpu_name_buffer[0..len], cpu[0..len]); + return cpu_name_buffer[0..len]; } -pub fn macos(allocator: std.mem.Allocator) !OsInfo { - const memory = try mac.getTotalMemory(allocator); - - return OsInfo{ - .allocator = allocator, - .platform = platform, - .cpu = try mac.getCpuName(allocator), - .cpu_cores = try mac.getCpuCores(allocator), - .memory_total = try format.memorySize(memory, allocator), +fn getCpuCores() !u32 { + var scratch: [4096]u8 = undefined; + var fbs = std.heap.FixedBufferAllocator.init(&scratch); + return switch (builtin.os.tag) { + .linux => try lnx.getCpuCores(fbs.allocator()), + .macos => try mac.getCpuCores(fbs.allocator()), + .windows => try win.getCpuCores(fbs.allocator()), + else => error.UnsupportedOs, }; } -pub fn windows(allocator: std.mem.Allocator) !OsInfo { - const memory = try win.getTotalMemory(allocator); - - return OsInfo{ - .allocator = allocator, - .platform = platform, - .cpu = try win.getCpuName(allocator), - .cpu_cores = try win.getCpuCores(allocator), - .memory_total = try format.memorySize(memory, allocator), +fn getTotalMemory() !u64 { + var scratch: [4096]u8 = undefined; + var fbs = std.heap.FixedBufferAllocator.init(&scratch); + return switch (builtin.os.tag) { + .linux => try lnx.getTotalMemory(fbs.allocator()), + .macos => try mac.getTotalMemory(fbs.allocator()), + .windows => try win.getTotalMemory(fbs.allocator()), + else => error.UnsupportedOs, }; } + +test "OsInfo" { + // No allocator and no free needed, it's stored statically. + const sysinfo = try getSystemInfo(); + try std.testing.expect(sysinfo.platform.len != 0); + try std.testing.expect(sysinfo.cpu.len != 0); + try std.testing.expect(0 < sysinfo.cpu_cores); + try std.testing.expect(0 < sysinfo.memory_total); +} diff --git a/zbench.zig b/zbench.zig index 2bddfe5..d241d8f 100644 --- a/zbench.zig +++ b/zbench.zig @@ -127,8 +127,8 @@ pub const Benchmark = struct { } /// Get a copy of the system information, cpu type, cores, memory, etc. - pub fn getSystemInfo(self: Benchmark) !platform.OsInfo { - return try platform.getSystemInfo(self.allocator); + pub fn getSystemInfo(_: Benchmark) !platform.OsInfo { + return try platform.getSystemInfo(); } };