diff --git a/bench/algorithm/binarytrees/1.zig b/bench/algorithm/binarytrees/1.zig index 1cec9e022..9f5270aa7 100644 --- a/bench/algorithm/binarytrees/1.zig +++ b/bench/algorithm/binarytrees/1.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const print = @import("print.zig"); const builtin = @import("builtin"); const math = std.math; const Allocator = std.mem.Allocator; @@ -7,14 +8,14 @@ const MIN_DEPTH = 4; const global_allocator = std.heap.c_allocator; pub fn main() !void { - const stdout = std.io.getStdOut().writer(); + // Zig 0.15: avoid std.io stdout writer; use a small fmt+write helper to stdout. const n = try get_n(); const max_depth = @max(MIN_DEPTH + 2, n); { const stretch_depth = max_depth + 1; const stretch_tree = Node.make(stretch_depth, global_allocator).?; defer stretch_tree.deinit(); - try stdout.print("stretch tree of depth {d}\t check: {d}\n", .{ stretch_depth, stretch_tree.check() }); + try print.printFmt("stretch tree of depth {d}\t check: {d}\n", .{ stretch_depth, stretch_tree.check() }); } const long_lived_tree = Node.make(max_depth, global_allocator).?; defer long_lived_tree.deinit(); @@ -29,17 +30,17 @@ pub fn main() !void { defer tree.deinit(); sum += tree.check(); } - try stdout.print("{d}\t trees of depth {d}\t check: {d}\n", .{ iterations, depth, sum }); + try print.printFmt("{d}\t trees of depth {d}\t check: {d}\n", .{ iterations, depth, sum }); } - try stdout.print("long lived tree of depth {d}\t check: {d}\n", .{ max_depth, long_lived_tree.check() }); + try print.printFmt("long lived tree of depth {d}\t check: {d}\n", .{ max_depth, long_lived_tree.check() }); } fn get_n() !usize { var arg_it = std.process.args(); _ = arg_it.skip(); const arg = arg_it.next() orelse return 10; - return try std.fmt.parseInt(u32, arg, 10); + return @as(usize, @intCast(try std.fmt.parseInt(u32, arg, 10))); } const Node = struct { diff --git a/bench/algorithm/coro-prime-sieve/1.zig b/bench/algorithm/coro-prime-sieve/1.zig index 7dcca23db..21c21a80f 100644 --- a/bench/algorithm/coro-prime-sieve/1.zig +++ b/bench/algorithm/coro-prime-sieve/1.zig @@ -2,6 +2,7 @@ // https://gist.github.com/SpexGuy/953e5780cd2d2c524cba6a79f13076e6 const std = @import("std"); +const print = @import("print.zig"); const Channel = struct { value: u32, @@ -34,7 +35,7 @@ fn filter(out_channel: *Channel, in_channel: *Channel, prime: u32) void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); const global_allocator = arena.allocator(); -const stdout = std.io.getStdOut().writer(); + pub fn main() !void { defer arena.deinit(); @@ -52,7 +53,7 @@ pub fn main() !void { while (i < n) : (i += 1) { resume ch.frame; const prime = ch.value; - try stdout.print("{}\n", .{prime}); + try print.printFmt("{}\n", .{prime}); if (i >= n - 1) break; const ch1 = try global_allocator.create(Channel); const frame = try global_allocator.create(@Frame(filter)); diff --git a/bench/algorithm/edigits/1.zig b/bench/algorithm/edigits/1.zig index c8b16410f..47f1b5cd6 100644 --- a/bench/algorithm/edigits/1.zig +++ b/bench/algorithm/edigits/1.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const print = @import("print.zig"); const bigint = std.math.big.int; const math = std.math; const global_allocator = std.heap.c_allocator; @@ -13,7 +14,6 @@ const Pair = struct { }; pub fn main() !void { - const stdout = std.io.getStdOut().writer(); const n = try get_n(); const k = binary_search(n); var pair = try sum_terms(0, k - 1); @@ -44,14 +44,15 @@ pub fn main() !void { j += 1; } if (i + 10 <= n_usize) { - try stdout.print("{s}\t:{d}\n", .{ sb, i + 10 }); + try print.printFmt("{s}\t:{d}\n", .{ sb, i + 10 }); } else { - try stdout.print("{s}\t:{d}\n", .{ sb, n }); + try print.printFmt("{s}\t:{d}\n", .{ sb, n }); } i += 10; } } + fn sum_terms(a: i32, b: i32) anyerror!Pair { if (b == a + 1) { const p = try bigint.Managed.initSet(global_allocator, 1); diff --git a/bench/algorithm/fannkuch-redux/1.zig b/bench/algorithm/fannkuch-redux/1.zig index 2565ca85f..e1b2ae530 100644 --- a/bench/algorithm/fannkuch-redux/1.zig +++ b/bench/algorithm/fannkuch-redux/1.zig @@ -1,6 +1,7 @@ // From https://github.com/tiehuis/zig-benchmarks-game/blob/master/src/fannkuch-redux.zig const std = @import("std"); +const print = @import("print.zig"); const global_allocator = std.heap.c_allocator; @@ -8,8 +9,8 @@ var buffer: [1024]u8 = undefined; var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer[0..]); var allocator = fixed_allocator.allocator(); + pub fn main() !void { - const stdout = std.io.getStdOut().writer(); const n = try get_n(); var perm = try allocator.alloc(usize, n); @@ -83,7 +84,7 @@ pub fn main() !void { } } - try stdout.print("{d}\nPfannkuchen({d}) = {d}\n", .{ checksum, n, max_flips_count }); + try print.printFmt("{d}\nPfannkuchen({d}) = {d}\n", .{ checksum, n, max_flips_count }); } fn get_n() !usize { diff --git a/bench/algorithm/fannkuch-redux/2-m.zig b/bench/algorithm/fannkuch-redux/2-m.zig index 0067619e6..60506fa1b 100644 --- a/bench/algorithm/fannkuch-redux/2-m.zig +++ b/bench/algorithm/fannkuch-redux/2-m.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const print = @import("print.zig"); const max_n = 12; const Vec = @Vector(max_n, u8); @@ -128,10 +129,10 @@ pub fn main() !void { const perms_count = factorialComptime(n); try runInParallel(tasks, perms_count, pfannkuchenStats, .{ n, &stats }); - const stdout = std.io.getStdOut().writer(); - try stdout.print("{d}\nPfannkuchen({d}) = {d}\n", .{ stats.checksum, n, stats.max_flips }); + try print.printFmt("{d}\nPfannkuchen({d}) = {d}\n", .{ stats.checksum, n, stats.max_flips }); } + fn get_n() !u8 { var arg_it = std.process.args(); _ = arg_it.skip(); diff --git a/bench/algorithm/fannkuch-redux/2.zig b/bench/algorithm/fannkuch-redux/2.zig index b583fc435..94529d9ab 100644 --- a/bench/algorithm/fannkuch-redux/2.zig +++ b/bench/algorithm/fannkuch-redux/2.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const print = @import("print.zig"); const Vec = @Vector(16, u8); @@ -25,7 +26,7 @@ fn next_perm_mask(n: u8) Vec { } fn apply_mask(a: Vec, n: u8, comptime mask: anytype) Vec { - const len = @typeInfo(Vec).Vector.len; + const len = @typeInfo(Vec).vector.len; comptime var i: u8 = 0; inline while (i < len) : (i += 1) if (i == n) return @shuffle(u8, a, undefined, mask(i)); unreachable; @@ -62,10 +63,10 @@ pub fn main() !void { for (count[1..r], 0..) |*v, i| v.* = @intCast(i + 2); } - const stdout = std.io.getStdOut().writer(); - try stdout.print("{d}\nPfannkuchen({d}) = {d}\n", .{ checksum, n, max_flip_count }); + try print.printFmt("{d}\nPfannkuchen({d}) = {d}\n", .{ checksum, n, max_flip_count }); } + fn get_n() !u8 { var arg_it = std.process.args(); _ = arg_it.skip(); diff --git a/bench/algorithm/fannkuch-redux/3-i.zig b/bench/algorithm/fannkuch-redux/3-i.zig index f88bcd25e..4c285e9f8 100644 --- a/bench/algorithm/fannkuch-redux/3-i.zig +++ b/bench/algorithm/fannkuch-redux/3-i.zig @@ -23,6 +23,9 @@ // const std = @import("std"); +const print = @import("print.zig"); + + const u8x16 = @Vector(16, u8); fn get_n() !u4 { @@ -35,8 +38,7 @@ fn get_n() !u4 { pub fn main() !void { const n = try get_n(); const x = fannkuchRedux(n); - const stdout = std.io.getStdOut().writer(); - try stdout.print("{}\nPfannkuchen({}) = {}\n", .{ x[0], n, x[1] }); + try print.printFmt("{}\nPfannkuchen({}) = {}\n", .{ x[0], n, x[1] }); } inline fn shuffle_epi8(x: u8x16, mask: u8x16) u8x16 { diff --git a/bench/algorithm/fasta/1.zig b/bench/algorithm/fasta/1.zig index 679bcdf2b..77f91a8bb 100644 --- a/bench/algorithm/fasta/1.zig +++ b/bench/algorithm/fasta/1.zig @@ -30,8 +30,8 @@ fn repeatAndWrap(out: anytype, comptime sequence: []const u8, count: usize) void const rem = count - idx; const line_length = @min(@as(usize, max_line_length), rem); - _ = out.write(padded_sequence[off .. off + line_length]) catch unreachable; - _ = out.writeByte('\n') catch unreachable; + _ = out.write(padded_sequence[off .. off + line_length]) catch unreachable; + _ = out.writeByte('\n') catch unreachable; off += line_length; if (off > sequence.len) { @@ -71,19 +71,22 @@ fn generateAndWrap(out: anytype, comptime nucleotides: []const AminoAcid, count: } line[line_length] = '\n'; - _ = out.write(line[0 .. line_length + 1]) catch unreachable; + _ = out.write(line[0 .. line_length + 1]) catch unreachable; idx += line_length; } } -var buffer: [256]u8 = undefined; -var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer[0..]); -var allocator = &fixed_allocator.allocator; +const Out = struct { + pub fn write(_: Out, bytes: []const u8) !usize { + return try std.posix.write(std.posix.STDOUT_FILENO, bytes); + } + pub fn writeByte(self: Out, b: u8) !void { + _ = try self.write(&[_]u8{b}); + } +}; pub fn main() !void { - var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); - defer buffered_stdout.flush() catch unreachable; - const stdout = buffered_stdout.writer(); + const stdout = Out{}; const n = try get_n(); const homo_sapiens_alu = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC" ++ "AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG" ++ diff --git a/bench/algorithm/helloworld/1.zig b/bench/algorithm/helloworld/1.zig index c714c89d0..b8ef65376 100644 --- a/bench/algorithm/helloworld/1.zig +++ b/bench/algorithm/helloworld/1.zig @@ -1,12 +1,13 @@ const std = @import("std"); +const print = @import("print.zig"); const global_allocator = std.heap.c_allocator; + pub fn main() !void { const args = try std.process.argsAlloc(global_allocator); defer std.process.argsFree(global_allocator, args); - const stdout = std.io.getStdOut().writer(); if (args.len > 1) { - try stdout.print("Hello world {s}!\n", .{args[1]}); + try print.printFmt("Hello world {s}!\n", .{args[1]}); } else { - try stdout.print("Hello world!\n", .{}); + try print.printFmt("Hello world!\n", .{}); } } diff --git a/bench/algorithm/json-serde/1.zig b/bench/algorithm/json-serde/1.zig index 68329c082..2e4af3ffd 100644 --- a/bench/algorithm/json-serde/1.zig +++ b/bench/algorithm/json-serde/1.zig @@ -1,8 +1,10 @@ const std = @import("std"); +const print = @import("print.zig"); const json = std.json; const global_allocator = std.heap.c_allocator; + pub fn main() !void { const args = try std.process.argsAlloc(global_allocator); defer std.process.argsFree(global_allocator, args); @@ -17,7 +19,6 @@ pub fn main() !void { if (args.len > 2) { n = try std.fmt.parseInt(usize, args[2], 10); } - const stdout = std.io.getStdOut().writer(); const json_str = try file.readToEndAlloc(global_allocator, std.math.maxInt(u32)); defer global_allocator.free(json_str); @@ -25,31 +26,31 @@ pub fn main() !void { const parsed = try json.parseFromSlice(GeoData, global_allocator, json_str, .{}); defer parsed.deinit(); const data = parsed.value; - var json_str_des = std.ArrayList(u8).init(global_allocator); - defer json_str_des.deinit(); - try json.stringify(data, .{}, json_str_des.writer()); - try printHash(json_str_des.items, stdout); + var json_str_des: std.ArrayList(u8) = .{}; + defer json_str_des.deinit(global_allocator); + try json.stringify(data, .{}, json_str_des.writer(global_allocator)); + try printHash(json_str_des.items); } { - var array = std.ArrayList(GeoData).init(global_allocator); + var array: std.ArrayList(GeoData) = .{}; var i: usize = 0; while (i < n) : (i += 1) { const parsed = try json.parseFromSlice(GeoData, global_allocator, json_str, .{}); // defer parsed.deinit(); - try array.append(parsed.value); + try array.append(global_allocator, parsed.value); } - var json_str_des = std.ArrayList(u8).init(global_allocator); - defer json_str_des.deinit(); - try json.stringify(array.items, .{}, json_str_des.writer()); - try printHash(json_str_des.items, stdout); + var json_str_des: std.ArrayList(u8) = .{}; + defer json_str_des.deinit(global_allocator); + try json.stringify(array.items, .{}, json_str_des.writer(global_allocator)); + try printHash(json_str_des.items); } } -fn printHash(bytes: []const u8, stdout: anytype) !void { +fn printHash(bytes: []const u8) !void { const Md5 = std.crypto.hash.Md5; var hash: [Md5.digest_length]u8 = undefined; Md5.hash(bytes, &hash, .{}); - try stdout.print("{s}\n", .{std.fmt.fmtSliceHexLower(&hash)}); + try print.printFmt("{s}\n", .{std.fmt.fmtSliceHexLower(&hash)}); } const GeoData = struct { diff --git a/bench/algorithm/knucleotide/1-m.zig b/bench/algorithm/knucleotide/1-m.zig index 3d1ad24ac..2203046d4 100644 --- a/bench/algorithm/knucleotide/1-m.zig +++ b/bench/algorithm/knucleotide/1-m.zig @@ -1,7 +1,8 @@ const std = @import("std"); +const print = @import("print.zig"); const gpa = std.heap.c_allocator; -const stdout = std.io.getStdOut().writer(); + const Code = struct { data: u64, @@ -28,7 +29,7 @@ const Code = struct { } pub fn toString(self: Code, frame: usize) ![]const u8 { - var result = std.ArrayList(u8).init(gpa); + var result: std.ArrayList(u8) = .{}; var code = self.data; for (0..frame) |_| { const c: u8 = switch (@as(u2, @truncate(code))) { @@ -37,11 +38,11 @@ const Code = struct { Code.encodeByte('G') => 'G', Code.encodeByte('C') => 'C', }; - try result.append(c); + try result.append(gpa, c); code >>= 2; } std.mem.reverse(u8, result.items); - return result.toOwnedSlice(); + return result.toOwnedSlice(gpa); } }; @@ -49,36 +50,30 @@ pub fn readInput() ![]const u8 { const args = try std.process.argsAlloc(gpa); defer std.process.argsFree(gpa, args); const file_name = if (args.len > 1) args[1] else "25000_in"; - const file = try std.fs.cwd().openFile(file_name, .{}); - var buffered_reader = std.io.bufferedReader(file.reader()); - const reader = buffered_reader.reader(); - { // skip past first lines starting with '>' - var i: u8 = 0; - while (i < 3) : (i += 1) { - while (true) { - const c = try reader.readByte(); - if (c == '>') break; - } - } - while (true) { - const c = try reader.readByte(); - if (c == '\n') break; + var file = try std.fs.cwd().openFile(file_name, .{}); + defer file.close(); + var whole = try file.readToEndAlloc(gpa, std.math.maxInt(u32)); + // find after third header line starting with '>' then the end of that line + var gt_count: u8 = 0; + var i: usize = 0; + while (i < whole.len and gt_count < 3) : (i += 1) { + if (whole[i] == '>') gt_count += 1; } - } - - var buf = try reader.readAllAlloc(gpa, std.math.maxInt(u32)); + while (i < whole.len and whole[i] != '\n') : (i += 1) {} + if (i < whole.len) i += 1; + var buf = whole[i..]; // In place, remove all newlines from buf and encode nucleotides // using only the last 2 bits in each byte. { - var i: usize = 0; - for (buf) |c| { + var j: usize = 0; + for (buf) |c| { if (c != '\n') { // Gives a -> 0x00, c -> 0x01, g -> 0x03, t -> 0x02 - buf[i] = (c >> 1) & 0x03; - i += 1; + buf[j] = (c >> 1) & 0x03; + j += 1; } } - buf.len = i; + buf.len = j; } return buf; } @@ -126,19 +121,21 @@ fn printMap(frame: usize, maps: []const Map) !void { } } - var cc: std.BoundedArray(CountCode, code_limit) = .{}; + var cc_storage: [code_limit]CountCode = undefined; + var cc_len: usize = 0; for (counts, 0..) |count, code_data| if (count > 0) { - cc.appendAssumeCapacity(.{ .count = count, .code = .{ .data = @intCast(code_data) } }); + cc_storage[cc_len] = .{ .count = count, .code = .{ .data = @intCast(code_data) } }; + cc_len += 1; }; - std.mem.sort(CountCode, cc.slice(), {}, CountCode.dsc); + std.mem.sort(CountCode, cc_storage[0..cc_len], {}, CountCode.dsc); - for (cc.slice()) |c| { - try stdout.print("{!s} {d:.3}\n", .{ + for (cc_storage[0..cc_len]) |c| { + try print.printFmt("{!s} {d:.3}\n", .{ c.code.toString(frame), @as(f32, @floatFromInt(c.count)) / @as(f32, @floatFromInt(total)) * 100.0, }); } - try stdout.print("\n", .{}); + try print.printFmt("\n", .{}); } fn printOcc(occ: []const u8, maps: []const Map) !void { @@ -147,7 +144,7 @@ fn printOcc(occ: []const u8, maps: []const Map) !void { for (maps) |m| { if (m.get(code)) |count| total += count; } - try stdout.print("{}\t{s}\n", .{ total, occ }); + try print.printFmt("{}\t{s}\n", .{ total, occ }); } fn runInParallel(task_count: usize, len: usize, comptime f: anytype, args: anytype) !void { diff --git a/bench/algorithm/knucleotide/1.zig b/bench/algorithm/knucleotide/1.zig index d8768ba8b..12d4d4a19 100644 --- a/bench/algorithm/knucleotide/1.zig +++ b/bench/algorithm/knucleotide/1.zig @@ -1,7 +1,8 @@ const std = @import("std"); +const print = @import("print.zig"); const global_allocator = std.heap.c_allocator; -const stdout = std.io.getStdOut().writer(); + const Code = struct { data: u64, @@ -28,7 +29,7 @@ const Code = struct { } pub fn toString(self: Code, frame: usize) ![]const u8 { - var result = std.ArrayList(u8).init(global_allocator); + var result: std.ArrayList(u8) = .{}; var code = self.data; var i: usize = 0; while (i < frame) : (i += 1) { @@ -39,11 +40,11 @@ const Code = struct { Code.encodeByte('C') => 'C', else => unreachable, }; - try result.append(c); + try result.append(global_allocator, c); code >>= 2; } std.mem.reverse(u8, result.items); - return result.toOwnedSlice(); + return result.toOwnedSlice(global_allocator); } }; @@ -51,36 +52,33 @@ pub fn readInput() ![]const u8 { const args = try std.process.argsAlloc(global_allocator); defer std.process.argsFree(global_allocator, args); const file_name = if (args.len > 1) args[1] else "25000_in"; - const file = try std.fs.cwd().openFile(file_name, .{}); - var buffered_reader = std.io.bufferedReader(file.reader()); - const reader = buffered_reader.reader(); - { // skip past first lines starting with '>' - var i: u8 = 0; - while (i < 3) : (i += 1) { - while (true) { - const c = try reader.readByte(); - if (c == '>') break; - } - } - while (true) { - const c = try reader.readByte(); - if (c == '\n') break; + var file = try std.fs.cwd().openFile(file_name, .{}); + defer file.close(); + var whole = try file.readToEndAlloc(global_allocator, std.math.maxInt(u32)); + // find after third header line starting with '>' then the end of that line + var gt_count: u8 = 0; + var i: usize = 0; + while (i < whole.len and gt_count < 3) : (i += 1) { + if (whole[i] == '>') { + gt_count += 1; } } - - var buf = try reader.readAllAlloc(global_allocator, std.math.maxInt(u32)); + // move i to end of current line + while (i < whole.len and whole[i] != '\n') : (i += 1) {} + if (i < whole.len) i += 1; // skip newline + var buf = whole[i..]; // In place, remove all newlines from buf and encode nucleotides // using only the last 2 bits in each byte. { - var i: usize = 0; + var j: usize = 0; for (buf) |c| { if (c != '\n') { // Gives a -> 0x00, c -> 0x01, g -> 0x03, t -> 0x02 - buf[i] = (c >> 1) & 0x03; - i += 1; + buf[j] = (c >> 1) & 0x03; + j += 1; } } - buf.len = i; + buf.len = j; } return buf; } @@ -138,32 +136,32 @@ const CountCode = struct { }; fn printMap(self: usize, map: Map) !void { - var v = std.ArrayList(CountCode).init(global_allocator); - defer v.deinit(); + var v: std.ArrayList(CountCode) = .{}; + defer v.deinit(global_allocator); var iter = map.iterator(); var total: u64 = 0; while (iter.next()) |it| { const count = it.value_ptr.*; total += count; - try v.append(.{ .count = count, .code = it.key_ptr.* }); + try v.append(global_allocator, .{ .count = count, .code = it.key_ptr.* }); } std.mem.sort(CountCode, v.items, {}, comptime CountCode.asc); var i = v.items.len - 1; while (true) : (i -= 1) { const cc = v.items[i]; - try stdout.print("{!s} {d:.3}\n", .{ + try print.printFmt("{!s} {d:.3}\n", .{ cc.code.toString(self), @as(f32, @floatFromInt(cc.count)) / @as(f32, @floatFromInt(total)) * 100.0, }); if (i == 0) break; } - try stdout.print("\n", .{}); + try print.printFmt("\n", .{}); } fn printOcc(s: []const u8, map: *Map) !void { const count = if (map.get(Code.fromStr(s))) |x| x else 0; - try stdout.print("{}\t{s}\n", .{ count, s }); + try print.printFmt("{}\t{s}\n", .{ count, s }); } pub fn main() !void { diff --git a/bench/algorithm/lru/1.zig b/bench/algorithm/lru/1.zig index 3b2315c6c..4f57c3fd8 100644 --- a/bench/algorithm/lru/1.zig +++ b/bench/algorithm/lru/1.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const print = @import("print.zig"); const builtin = @import("builtin"); const Allocator = std.mem.Allocator; const HashMap = std.HashMap; @@ -6,8 +7,8 @@ const AutoContext = std.hash_map.AutoContext; const global_allocator = std.heap.c_allocator; + pub fn main() !void { - const stdout = std.io.getStdOut().writer(); const args = try get_args(); const size = args[0]; const n = args[1]; @@ -29,7 +30,7 @@ pub fn main() !void { hit += 1; } } - try stdout.print("{d}\n{d}\n", .{ hit, missed }); + try print.printFmt("{d}\n{d}\n", .{ hit, missed }); } fn get_args() ![2]u32 { diff --git a/bench/algorithm/mandelbrot/1.zig b/bench/algorithm/mandelbrot/1.zig index 9d087d9de..496a26588 100644 --- a/bench/algorithm/mandelbrot/1.zig +++ b/bench/algorithm/mandelbrot/1.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const print = @import("print.zig"); const ArrayList = std.ArrayList; const md5 = std.crypto.hash.Md5; @@ -7,13 +8,14 @@ const Vec = @Vector(VEC_SIZE, f64); const global_allocator = std.heap.c_allocator; + pub fn main() !void { const n = try get_n(); const size = (n + VEC_SIZE - 1) / VEC_SIZE * VEC_SIZE; const chunk_size = size / VEC_SIZE; const inv = 2.0 / @as(f64, @floatFromInt(size)); - var xloc = ArrayList(Vec).init(global_allocator); - try xloc.ensureTotalCapacityPrecise(chunk_size); + var xloc: ArrayList(Vec) = .{}; + try xloc.ensureTotalCapacityPrecise(global_allocator, chunk_size); var i: usize = 0; while (i < chunk_size) : (i += 1) { const offset = i * VEC_SIZE; @@ -27,28 +29,35 @@ pub fn main() !void { init_xloc(offset + 6, inv), init_xloc(offset + 7, inv), }; - try xloc.append(v); + try xloc.append(global_allocator, v); } - const stdout = std.io.getStdOut().writer(); - try stdout.print("P4\n{d} {d}\n", .{ size, size }); + try print.printFmt("P4\n{d} {d}\n", .{ size, size }); - var pixels = ArrayList(u8).init(global_allocator); - try pixels.ensureTotalCapacityPrecise(size * chunk_size); + var pixels: ArrayList(u8) = .{}; + try pixels.ensureTotalCapacityPrecise(global_allocator, size * chunk_size); var y: usize = 0; while (y < size) : (y += 1) { const ci = @as(f64, @floatFromInt(y)) * inv - 1.0; var x: usize = 0; while (x < chunk_size) : (x += 1) { const r = mbrot8(xloc.items[x], ci); - try pixels.append(r); + try pixels.append(global_allocator, r); } } // try stdout.print("{}\n", .{pixels}); var hash: [16]u8 = undefined; md5.hash(pixels.items, &hash, .{}); - try stdout.print("{}\n", .{std.fmt.fmtSliceHexLower(&hash)}); + var hex: [32]u8 = undefined; + inline for (hash, 0..) |b, idx| { + const j = idx * 2; + const hi = (b >> 4) & 0x0F; + const lo = b & 0x0F; + hex[j] = if (hi < 10) '0' + hi else 'a' + (hi - 10); + hex[j + 1] = if (lo < 10) '0' + lo else 'a' + (lo - 10); + } + try print.printFmt("{s}\n", .{hex}); } fn mbrot8(cr: Vec, civ: f64) u8 { diff --git a/bench/algorithm/merkletrees/1.zig b/bench/algorithm/merkletrees/1.zig index 3c3ade416..4317c6267 100644 --- a/bench/algorithm/merkletrees/1.zig +++ b/bench/algorithm/merkletrees/1.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const print = @import("print.zig"); const builtin = @import("builtin"); const math = std.math; const Allocator = std.mem.Allocator; @@ -6,8 +7,8 @@ const MIN_DEPTH = 4; const global_allocator = std.heap.c_allocator; + pub fn main() !void { - const stdout = std.io.getStdOut().writer(); const n = try get_n(); const max_depth = @max(MIN_DEPTH + 2, n); { @@ -15,7 +16,7 @@ pub fn main() !void { const stretch_tree = Node.make(stretch_depth, global_allocator).?; defer stretch_tree.deinit(); stretch_tree.cal_hash(); - try stdout.print("stretch tree of depth {d}\t root hash: {d} check: {!}\n", .{ stretch_depth, stretch_tree.get_hash(), stretch_tree.check() }); + try print.printFmt("stretch tree of depth {d}\t root hash: {d} check: {}\n", .{ stretch_depth, stretch_tree.get_hash(), stretch_tree.check() }); } const long_lived_tree = Node.make(max_depth, global_allocator).?; defer long_lived_tree.deinit(); @@ -31,10 +32,10 @@ pub fn main() !void { tree.cal_hash(); sum += tree.get_hash(); } - try stdout.print("{d}\t trees of depth {d}\t root hash sum: {d}\n", .{ iterations, depth, sum }); + try print.printFmt("{d}\t trees of depth {d}\t root hash sum: {d}\n", .{ iterations, depth, sum }); } long_lived_tree.cal_hash(); - try stdout.print("long lived tree of depth {d}\t root hash: {d} check: {!}\n", .{ max_depth, long_lived_tree.get_hash(), long_lived_tree.check() }); + try print.printFmt("long lived tree of depth {d}\t root hash: {d} check: {}\n", .{ max_depth, long_lived_tree.get_hash(), long_lived_tree.check() }); } fn get_n() !usize { diff --git a/bench/algorithm/nbody/1.zig b/bench/algorithm/nbody/1.zig index cb053a666..c1b86be4c 100644 --- a/bench/algorithm/nbody/1.zig +++ b/bench/algorithm/nbody/1.zig @@ -1,6 +1,7 @@ // From https://github.com/tiehuis/zig-benchmarks-game/blob/master/src/n-body.zig const std = @import("std"); +const print = @import("print.zig"); const builtin = @import("builtin"); const math = std.math; @@ -149,19 +150,19 @@ var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer[0..]); var allocator = &fixed_allocator.allocator; pub fn main() !void { - const stdout = std.io.getStdOut().writer(); const n = try get_n(); var bodies = solar_bodies; offset_momentum(bodies[0..]); var ret = energy(bodies[0..]); - try stdout.print("{d:.9}\n", .{ret}); + try print.printFmt("{d:.9}\n", .{ret}); advance(bodies[0..], 0.01, n); ret = energy(bodies[0..]); - try stdout.print("{d:.9}\n", .{ret}); + try print.printFmt("{d:.9}\n", .{ret}); } + fn get_n() !usize { var arg_it = std.process.args(); _ = arg_it.skip(); diff --git a/bench/algorithm/nbody/2.zig b/bench/algorithm/nbody/2.zig index 5c1208b8e..8ff8f4c90 100644 --- a/bench/algorithm/nbody/2.zig +++ b/bench/algorithm/nbody/2.zig @@ -1,6 +1,8 @@ const std = @import("std"); +const print = @import("print.zig"); const math = std.math; + const solar_mass = 4.0 * math.pi * math.pi; const year = 365.24; @@ -112,8 +114,7 @@ pub fn main() !void { for (range(steps)) |_| advance(&solar_bodies, 0.01); const final_energy = energy(&solar_bodies); - const stdout = std.io.getStdOut().writer(); - try stdout.print("{d:.9}\n{d:.9}\n", .{ initial_energy, final_energy }); + try print.printFmt("{d:.9}\n{d:.9}\n", .{ initial_energy, final_energy }); } fn get_steps() !usize { diff --git a/bench/algorithm/nbody/3.zig b/bench/algorithm/nbody/3.zig index 55056fe19..7920deb84 100644 --- a/bench/algorithm/nbody/3.zig +++ b/bench/algorithm/nbody/3.zig @@ -1,6 +1,8 @@ const std = @import("std"); +const print = @import("print.zig"); const math = std.math; + const solar_mass = 4.0 * math.pi * math.pi; const year = 365.24; @@ -114,8 +116,7 @@ pub fn main() !void { for (0..steps) |_| advance(solar_bodies.len, &solar_bodies, 0.01); const final_energy = energy(&solar_bodies); - const stdout = std.io.getStdOut().writer(); - try stdout.print("{d:.9}\n{d:.9}\n", .{ initial_energy, final_energy }); + try print.printFmt("{d:.9}\n{d:.9}\n", .{ initial_energy, final_energy }); } fn getSteps() !usize { diff --git a/bench/algorithm/nsieve/1.zig b/bench/algorithm/nsieve/1.zig index 416b2ee7b..f4e3565be 100644 --- a/bench/algorithm/nsieve/1.zig +++ b/bench/algorithm/nsieve/1.zig @@ -1,7 +1,9 @@ const std = @import("std"); +const print = @import("print.zig"); const global_allocator = std.heap.c_allocator; + fn nsieve(n: usize) !void { var count: usize = 0; var flags = try global_allocator.alloc(bool, n); @@ -17,8 +19,7 @@ fn nsieve(n: usize) !void { } } } - const stdout = std.io.getStdOut().writer(); - try stdout.print("Primes up to {d:8} {d:8}\n", .{ n, count }); + try print.printFmt("Primes up to {d:8} {d:8}\n", .{ n, count }); } pub fn main() !void { diff --git a/bench/algorithm/nsieve/2.zig b/bench/algorithm/nsieve/2.zig index 3441fc68b..e7f7ddfc7 100644 --- a/bench/algorithm/nsieve/2.zig +++ b/bench/algorithm/nsieve/2.zig @@ -1,8 +1,10 @@ const std = @import("std"); +const print = @import("print.zig"); const DynamicBitSet = std.bit_set.DynamicBitSet; const global_allocator = std.heap.c_allocator; + fn nsieve(n: usize) !void { var count: usize = 0; var flags = try DynamicBitSet.initEmpty(global_allocator, n); @@ -17,8 +19,7 @@ fn nsieve(n: usize) !void { } } } - const stdout = std.io.getStdOut().writer(); - try stdout.print("Primes up to {d:8} {d:8}\n", .{ n, count }); + try print.printFmt("Primes up to {d:8} {d:8}\n", .{ n, count }); } pub fn main() !void { diff --git a/bench/algorithm/pidigits/1.zig b/bench/algorithm/pidigits/1.zig index 031322f6a..03c920b47 100644 --- a/bench/algorithm/pidigits/1.zig +++ b/bench/algorithm/pidigits/1.zig @@ -1,9 +1,10 @@ const std = @import("std"); +const print = @import("print.zig"); const bigint = std.math.big.int; const global_allocator = std.heap.c_allocator; + pub fn main() !void { - const stdout = std.io.getStdOut().writer(); const n = try get_n(); const one = (try bigint.Managed.initSet(global_allocator, 1)); @@ -34,12 +35,12 @@ pub fn main() !void { _ = u.toConst().toString(sb[rem..], 10, .lower, &lbuf); digits_printed += 1; if (rem == 9) - try stdout.print("{s}\t:{d}\n", .{ sb, digits_printed }); + try print.printFmt("{s}\t:{d}\n", .{ sb, digits_printed }); if (digits_printed >= n) { if (rem != 9) { @memset(sb[rem + 1 ..], ' '); - try stdout.print("{s}\t:{d}\n", .{ sb, digits_printed }); + try print.printFmt("{s}\t:{d}\n", .{ sb, digits_printed }); } break; } diff --git a/bench/algorithm/spectral-norm/1.zig b/bench/algorithm/spectral-norm/1.zig index f170563e9..c66e397b9 100644 --- a/bench/algorithm/spectral-norm/1.zig +++ b/bench/algorithm/spectral-norm/1.zig @@ -1,9 +1,11 @@ // From https://github.com/tiehuis/zig-benchmarks-game/blob/master/src/spectral-norm.zig const std = @import("std"); +const print = @import("print.zig"); const global_allocator = std.heap.c_allocator; + fn eval_a(i: usize, j: usize) f64 { return 1.0 / @as(f64, @floatFromInt((i + j) * (i + j + 1) / 2 + i + 1)); } @@ -36,7 +38,6 @@ fn eval_ata_times_u(atau: []f64, u: []const f64, scratch: []f64) void { } pub fn main() !void { - const stdout = std.io.getStdOut().writer(); const n = try get_n(); const u = try global_allocator.alloc(f64, n); @@ -58,11 +59,11 @@ pub fn main() !void { var j: usize = 0; while (j < n) : (j += 1) { - vbv += u[i] * v[i]; - vv += v[i] * v[i]; + vbv += u[j] * v[j]; + vv += v[j] * v[j]; } - try stdout.print("{d:.9}\n", .{std.math.sqrt(vbv / vv)}); + try print.printFmt("{d:.9}\n", .{std.math.sqrt(vbv / vv)}); } fn get_n() !usize { diff --git a/bench/algorithm/spectral-norm/2-m.zig b/bench/algorithm/spectral-norm/2-m.zig index 8769bfed0..4873d99d5 100644 --- a/bench/algorithm/spectral-norm/2-m.zig +++ b/bench/algorithm/spectral-norm/2-m.zig @@ -1,4 +1,6 @@ const std = @import("std"); +const print = @import("print.zig"); + const vec4 = @Vector(4, f64); fn vec1to4(f: f64) vec4 { @@ -69,7 +71,7 @@ fn aggregateResults(first: usize, last: usize, u: []const vec4, v: []const vec4, pub fn main() !void { const n = try get_n(); - const len = n / @typeInfo(vec4).Vector.len; + const len = n / @typeInfo(vec4).vector.len; const allocator = std.heap.c_allocator; const u = try allocator.alloc(vec4, len); @@ -96,8 +98,7 @@ pub fn main() !void { try runInParallel(tasks, u.len, aggregateResults, .{ u, v, &vbv, &vv }); const res = std.math.sqrt(vbv / vv); - const stdout = std.io.getStdOut().writer(); - try stdout.print("{d:.9}\n", .{res}); + try print.printFmt("{d:.9}\n", .{res}); } fn get_n() !usize { diff --git a/bench/algorithm/spectral-norm/2.zig b/bench/algorithm/spectral-norm/2.zig index 653cbe8ce..35429a3dc 100644 --- a/bench/algorithm/spectral-norm/2.zig +++ b/bench/algorithm/spectral-norm/2.zig @@ -1,4 +1,6 @@ const std = @import("std"); +const print = @import("print.zig"); + const vec4 = @Vector(4, f64); fn vec1to4(f: f64) vec4 { @@ -80,8 +82,7 @@ pub fn main() !void { const res = aggregateResults(u, v); - const stdout = std.io.getStdOut().writer(); - try stdout.print("{d:.9}\n", .{res}); + try print.printFmt("{d:.9}\n", .{res}); } fn get_n() !usize { diff --git a/bench/bench_zig.yaml b/bench/bench_zig.yaml index a72eda507..7234076fc 100644 --- a/bench/bench_zig.yaml +++ b/bench/bench_zig.yaml @@ -65,6 +65,8 @@ environments: version: latest docker: include: zig - build: zig build -Dcpu=broadwell # --verbose-llvm-cpu-features - out_dir: zig-out/bin + build: zig build-exe app.zig -OReleaseFast -mcpu=ivybridge -lc + after_build: + - mv app out + out_dir: out run_cmd: app diff --git a/bench/include/.gitignore b/bench/include/.gitignore index 130e08257..b5f0334e5 100644 --- a/bench/include/.gitignore +++ b/bench/include/.gitignore @@ -5,3 +5,4 @@ !kotlin-jvm/* !kotlin-native/* !nim.nimble +!zig/* diff --git a/bench/include/zig/.gitignore b/bench/include/zig/.gitignore index 3e753796d..9ac56e5dd 100644 --- a/bench/include/zig/.gitignore +++ b/bench/include/zig/.gitignore @@ -1,3 +1,4 @@ * !.gitignore !build.zig +!print.zig \ No newline at end of file diff --git a/bench/include/zig/build.zig b/bench/include/zig/build.zig index 4fc3ec1f1..ec42c4d8d 100644 --- a/bench/include/zig/build.zig +++ b/bench/include/zig/build.zig @@ -7,16 +7,16 @@ pub fn build(b: *std.Build) void { // for restricting supported target set are available. const target = b.standardTargetOptions(.{}); // Standard optimization options allow the person running `zig build` to select - // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not - // set a preferred release mode, allowing the user to decide how to optimize. - // const optimize = b.standardOptimizeOption(.{}); + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we default + // to ReleaseFast for benchmark performance. + const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast }); const exe = b.addExecutable(.{ .name = "app", - .root_source_file = b.path("app.zig"), - .target = target, - .optimize = std.builtin.Mode.ReleaseFast, + .root_module = b.createModule(.{ .root_source_file = b.path("app.zig") }), }); + exe.setTarget(target); + exe.setOptimizeMode(optimize); exe.linkLibC(); b.installArtifact(exe); diff --git a/bench/include/zig/print.zig b/bench/include/zig/print.zig new file mode 100644 index 000000000..a5208551a --- /dev/null +++ b/bench/include/zig/print.zig @@ -0,0 +1,16 @@ +//! Centralized print utility for Zig benchmarks +//! +//! This file was created to consolidate I/O handling across all Zig benchmark implementations +//! And simplitication of update to Zig >= 0.15 StdLib breaking change +//! Usage: const print = @import("../../include/zig/print.zig"); +//! try print.printFmt("Hello {s}!\n", .{"world"}); + +const std = @import("std"); + +/// Universal formatted print function for benchmark output +/// Uses a 256-byte stack buffer and direct stdout write for performance +pub fn printFmt(comptime fmt: []const u8, args: anytype) !void { + var buf: [256]u8 = undefined; + const out = try std.fmt.bufPrint(&buf, fmt, args); + _ = try std.posix.write(std.posix.STDOUT_FILENO, out); +}