From 6a739ef93afec890efef6cc3ebc76ace2f84bea3 Mon Sep 17 00:00:00 2001 From: zigster64 Date: Tue, 12 Jul 2022 12:41:24 +1000 Subject: [PATCH 1/3] Fix zig binary tree, and use arena allocator for better alloc performance --- bench/algorithm/binarytrees/1.zig | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/bench/algorithm/binarytrees/1.zig b/bench/algorithm/binarytrees/1.zig index 658fdf6c..6903a184 100644 --- a/bench/algorithm/binarytrees/1.zig +++ b/bench/algorithm/binarytrees/1.zig @@ -1,23 +1,25 @@ const std = @import("std"); +const print = std.io.getStdOut().writer().print; const builtin = @import("builtin"); const math = std.math; const Allocator = std.mem.Allocator; -const MIN_DEPTH = 4; -var gpa = std.heap.GeneralPurposeAllocator(.{}){}; -var global_allocator = gpa.allocator(); +const MIN_DEPTH = 4; pub fn main() !void { - const stdout = std.io.getStdOut().writer(); + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var alloc = arena.allocator(); + const n = try get_n(); const max_depth = math.max(MIN_DEPTH + 2, n); { const stretch_depth = max_depth + 1; - const stretch_tree = Node.make(stretch_depth, global_allocator).?; + const stretch_tree = Node.make(stretch_depth, alloc).?; defer stretch_tree.deinit(); - try stdout.print("stretch tree of depth {d}\t check: {d}\n", .{ stretch_depth, stretch_tree.check() }); + try print("stretch tree of depth {d}\t check: {d}\n", .{ stretch_depth, stretch_tree.check() }); } - const long_lived_tree = Node.make(max_depth, global_allocator).?; + const long_lived_tree = Node.make(max_depth, alloc).?; defer long_lived_tree.deinit(); var depth: usize = MIN_DEPTH; @@ -25,15 +27,16 @@ pub fn main() !void { const iterations = @intCast(usize, 1) << @intCast(u6, max_depth - depth + MIN_DEPTH); var sum: usize = 0; var i: usize = 0; + while (i < iterations) : (i += 1) { - const tree = Node.make(depth, global_allocator).?; + const tree = Node.make(depth, alloc).?; defer tree.deinit(); sum += tree.check(); } - try stdout.print("{d}\t trees of depth {d}\t check: {d}\n", .{ iterations, depth, sum }); + try print("{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("long lived tree of depth {d}\t check: {d}\n", .{ max_depth, long_lived_tree.check() }); } fn get_n() !usize { @@ -53,6 +56,9 @@ const Node = struct { pub fn init(allocator: Allocator) !*Self { var node = try allocator.create(Self); + // need to init the values of the node, because malloc + node.left = null; + node.right = null; node.allocator = allocator; return node; } @@ -68,7 +74,7 @@ const Node = struct { } pub fn make(depth: usize, allocator: Allocator) ?*Self { - var node = Self.init(allocator) catch return null; + var node = Self.init(allocator) catch unreachable; if (depth > 0) { const d = depth - 1; node.left = Self.make(d, allocator); From 780ea88e6ed36dd36054c67bcac69dd306f332af Mon Sep 17 00:00:00 2001 From: zigster64 Date: Tue, 12 Jul 2022 15:27:46 +1000 Subject: [PATCH 2/3] rename get_n to getN --- bench/algorithm/binarytrees/1.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bench/algorithm/binarytrees/1.zig b/bench/algorithm/binarytrees/1.zig index 6903a184..84f66c2d 100644 --- a/bench/algorithm/binarytrees/1.zig +++ b/bench/algorithm/binarytrees/1.zig @@ -11,7 +11,7 @@ pub fn main() !void { defer arena.deinit(); var alloc = arena.allocator(); - const n = try get_n(); + const n = try getN(); const max_depth = math.max(MIN_DEPTH + 2, n); { const stretch_depth = max_depth + 1; @@ -39,7 +39,7 @@ pub fn main() !void { try print("long lived tree of depth {d}\t check: {d}\n", .{ max_depth, long_lived_tree.check() }); } -fn get_n() !usize { +fn getN() !usize { var arg_it = std.process.args(); _ = arg_it.skip(); const arg = arg_it.next() orelse return 10; From 233333f9159743dc90994bd76f7cbf90e0fccd09 Mon Sep 17 00:00:00 2001 From: zigster64 Date: Tue, 12 Jul 2022 15:55:57 +1000 Subject: [PATCH 3/3] use threads for even faster --- bench/algorithm/binarytrees/1.zig | 49 ++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/bench/algorithm/binarytrees/1.zig b/bench/algorithm/binarytrees/1.zig index 84f66c2d..1114310e 100644 --- a/bench/algorithm/binarytrees/1.zig +++ b/bench/algorithm/binarytrees/1.zig @@ -3,9 +3,12 @@ const print = std.io.getStdOut().writer().print; const builtin = @import("builtin"); const math = std.math; const Allocator = std.mem.Allocator; +const Thread = std.Thread; const MIN_DEPTH = 4; +const CheckPass = struct { iterations: usize, depth: usize, sum: usize }; + pub fn main() !void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); @@ -23,22 +26,52 @@ pub fn main() !void { defer long_lived_tree.deinit(); var depth: usize = MIN_DEPTH; + + var threads = std.ArrayList(std.Thread).init(alloc); + defer threads.deinit(); + + var sums = std.ArrayList(CheckPass).init(alloc); + defer sums.deinit(); + var i: usize = 0; + while (depth <= max_depth) : (depth += 2) { const iterations = @intCast(usize, 1) << @intCast(u6, max_depth - depth + MIN_DEPTH); - var sum: usize = 0; - var i: usize = 0; + try sums.append(CheckPass{ + .iterations = iterations, + .depth = depth, + .sum = 0, + }); - while (i < iterations) : (i += 1) { - const tree = Node.make(depth, alloc).?; - defer tree.deinit(); - sum += tree.check(); - } - try print("{d}\t trees of depth {d}\t check: {d}\n", .{ iterations, depth, sum }); + const thread = try Thread.spawn(.{}, calc, .{&sums.items[i]}); + try threads.append(thread); + i += 1; + } + + i = 0; + for (threads.items) |thread| { + thread.join(); + const c = sums.items[i]; + try print("{d}\t trees of depth {d}\t check: {d}\n", .{ c.iterations, c.depth, c.sum }); + i += 1; } try print("long lived tree of depth {d}\t check: {d}\n", .{ max_depth, long_lived_tree.check() }); } +fn calc(check: *CheckPass) !void { + // each thread needs its own allocator + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + var alloc = arena.allocator(); + + var i: usize = 0; + while (i < check.iterations) : (i += 1) { + const tree = Node.make(check.depth, alloc).?; + defer tree.deinit(); + check.sum += tree.check(); + } +} + fn getN() !usize { var arg_it = std.process.args(); _ = arg_it.skip();