From 3d29bd65faffb8e04602051f04e5dcfc2ce355e5 Mon Sep 17 00:00:00 2001 From: Skirmantas Jurgaitis Date: Tue, 28 Mar 2023 23:54:58 +0200 Subject: [PATCH 1/2] Add Zig solution for binarytrees that use MemoryPool --- bench/algorithm/binarytrees/2.zig | 125 ++++++++++++++++++++++++++++++ bench/bench_zig.yaml | 3 + 2 files changed, 128 insertions(+) create mode 100644 bench/algorithm/binarytrees/2.zig diff --git a/bench/algorithm/binarytrees/2.zig b/bench/algorithm/binarytrees/2.zig new file mode 100644 index 00000000..6c0f1d7f --- /dev/null +++ b/bench/algorithm/binarytrees/2.zig @@ -0,0 +1,125 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const math = std.math; +const Allocator = std.mem.Allocator; +const MIN_DEPTH = 4; + +pub fn main() !void { + const global_allocator = std.heap.c_allocator; + const stdout = std.io.getStdOut().writer(); + const n = try get_n(global_allocator); + const max_depth = math.max(MIN_DEPTH + 2, n); + { + const stretch_depth = max_depth + 1; + const stretch_tree = try Tree.init(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() }); + } + const long_lived_tree = try Tree.init(max_depth, global_allocator); + defer long_lived_tree.deinit(); + + var depth: usize = MIN_DEPTH; + 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; + while (i < iterations) : (i += 1) { + const tree = try Tree.init(depth, global_allocator); + defer tree.deinit(); + sum += tree.check(); + } + try stdout.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() }); +} + +fn get_n(allocator: Allocator) !usize { + var arg_it = try std.process.ArgIterator.initWithAllocator(allocator); + defer arg_it.deinit(); + _ = arg_it.skip(); + const arg = arg_it.next() orelse return 10; + return try std.fmt.parseInt(u32, arg, 10); +} + +const NodePool = std.heap.MemoryPool(Node); + +const Tree = struct { + node_pool: NodePool, + root_node: *Node, + + pub fn init(depth: usize, allocator: Allocator) !Tree { + var node_pool = NodePool.init(allocator); + var root_node = Node.create_tree(&node_pool, depth) catch |err| { + node_pool.deinit(); + return err; + }; + return Tree{ .node_pool = node_pool, .root_node = root_node }; + } + + pub fn check(self: Tree) usize { + return self.root_node.check(); + } + + pub fn deinit(self: Tree) void { + @constCast(&self.node_pool).deinit(); + } +}; + +const Node = struct { + left: ?*Node = null, + right: ?*Node = null, + + pub fn check(node: *Node) usize { + var sum: usize = 1; + if (node.left) |left| sum += left.check(); + if (node.right) |right| sum += right.check(); + return sum; + } + + pub fn create_tree(pool: *NodePool, depth: usize) !*Node { + var node: *Node = try pool.create(); + if (depth > 0) { + const sub_tree_depth = depth - 1; + node.left = try create_tree(pool, sub_tree_depth); + node.right = try create_tree(pool, sub_tree_depth); + } else { + node.left = null; + node.right = null; + } + return node; + } +}; + +test "Test depth 0" { + var tree1 = try Tree.init(0, std.testing.allocator); + defer tree1.deinit(); + try std.testing.expect(tree1.check() == 1); +} + +test "Test depth 1" { + var tree1 = try Tree.init(1, std.testing.allocator); + defer tree1.deinit(); + try std.testing.expect(tree1.check() == 3); +} + +test "Test depth 2" { + var tree1 = try Tree.init(2, std.testing.allocator); + defer tree1.deinit(); + try std.testing.expect(tree1.check() == 7); +} + +test "Test multiple trees" { + var tree1 = try Tree.init(2, std.testing.allocator); + defer tree1.deinit(); + + var tree2 = try Tree.init(2, std.testing.allocator); + defer tree2.deinit(); + + var tree3 = try Tree.init(2, std.testing.allocator); + defer tree3.deinit(); + + try std.testing.expect(tree1.check() == 7); + try std.testing.expect(tree2.check() == 7); + try std.testing.expect(tree3.check() == 7); +} diff --git a/bench/bench_zig.yaml b/bench/bench_zig.yaml index ffe8b368..f6626b7b 100644 --- a/bench/bench_zig.yaml +++ b/bench/bench_zig.yaml @@ -6,6 +6,9 @@ problems: - name: binarytrees source: - 1.zig + - name: binarytrees + source: + - 2.zig - name: merkletrees source: - 1.zig From 8a917be00ea2efec7160022f12f655d37a5c93ed Mon Sep 17 00:00:00 2001 From: Skirmantas Jurgaitis Date: Thu, 30 Mar 2023 19:54:13 +0200 Subject: [PATCH 2/2] Fix struct methods: should be using pointer arguments --- bench/algorithm/binarytrees/2.zig | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bench/algorithm/binarytrees/2.zig b/bench/algorithm/binarytrees/2.zig index 6c0f1d7f..096bd1bd 100644 --- a/bench/algorithm/binarytrees/2.zig +++ b/bench/algorithm/binarytrees/2.zig @@ -11,11 +11,11 @@ pub fn main() !void { const max_depth = math.max(MIN_DEPTH + 2, n); { const stretch_depth = max_depth + 1; - const stretch_tree = try Tree.init(stretch_depth, global_allocator); + var stretch_tree = try Tree.init(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() }); } - const long_lived_tree = try Tree.init(max_depth, global_allocator); + var long_lived_tree = try Tree.init(max_depth, global_allocator); defer long_lived_tree.deinit(); var depth: usize = MIN_DEPTH; @@ -24,7 +24,7 @@ pub fn main() !void { var sum: usize = 0; var i: usize = 0; while (i < iterations) : (i += 1) { - const tree = try Tree.init(depth, global_allocator); + var tree = try Tree.init(depth, global_allocator); defer tree.deinit(); sum += tree.check(); } @@ -57,12 +57,13 @@ const Tree = struct { return Tree{ .node_pool = node_pool, .root_node = root_node }; } - pub fn check(self: Tree) usize { + pub fn check(self: *Tree) usize { return self.root_node.check(); } - pub fn deinit(self: Tree) void { - @constCast(&self.node_pool).deinit(); + pub fn deinit(self: *Tree) void { + self.node_pool.deinit(); + self.* = undefined; } };