z1brc

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit aeeabc0b34c21bb435a4243f17e37c577411a1ce
parent 25f18c4261eac8834bb96809c5e3b9f17b5d536d
Author: Martin Ashby <martin@ashbysoft.com>
Date:   Tue, 30 Jan 2024 12:43:00 +0000

Remove allocations from hot loop

Diffstat:
Msrc/main.zig | 98+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 58 insertions(+), 40 deletions(-)

diff --git a/src/main.zig b/src/main.zig @@ -1,8 +1,12 @@ const std = @import("std"); +pub const std_options = struct { + pub const log_level = .info; +}; + pub fn main() !void { var t = try std.time.Timer.start(); - std.log.err("start!", .{}); + std.log.info("start!", .{}); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); @@ -19,12 +23,12 @@ pub fn main() !void { defer a.free(out); try std.io.getStdOut().writeAll(out); - std.log.err("finished at {} s", .{t.read() / std.time.ns_per_s}); + std.log.info("finished at {} s", .{t.read() / std.time.ns_per_s}); } fn run(a: std.mem.Allocator, infile: []const u8, t: *std.time.Timer) ![]const u8 { - std.log.err("mmap done, iterating!", .{}); + std.log.info("mmap done, iterating!", .{}); var res = std.StringArrayHashMap(Accumulator).init(a); defer { var it = res.iterator(); @@ -38,43 +42,49 @@ fn run(a: std.mem.Allocator, infile: []const u8, t: *std.time.Timer) ![]const u8 while (lines.next()) |line| { ct += 1; if (ct % 100000 == 0) { - std.log.err("processed {} lines at {} seconds", .{ct, t.read() / std.time.ns_per_s}); + std.log.info("processed {} lines at {} seconds", .{ct, t.read() / std.time.ns_per_s}); } var spl = std.mem.splitScalar(u8, line, ';'); const key = spl.first(); - const val_s = spl.next() orelse return error.Malformatted; + var val_s = spl.next() orelse unreachable; var val: u16 = 0; - var is_neg: bool = false; + const is_neg: bool = val_s[0] == '-'; + if (is_neg) { + val_s = val_s[1..]; + } for (val_s) |c| { - if (c == '-') { - is_neg = true; - } else if (c >= '0' and c <= '9') { + if (c >= '0' and c <= '9') { const x = c - '0'; val *= 10; val += x; } } - if (!is_neg) { + if (is_neg) { + val = 999-val; + } else { val += 999; } - const kd = try a.dupe(u8, key); - const gpr = try res.getOrPut(kd); - if (gpr.found_existing) { - a.free(kd); - const e = gpr.value_ptr.*; - gpr.value_ptr.* = .{ + + // if (std.mem.eql(u8, key, "Istanbul")) { + // std.log.warn("Istanbul val {}", .{val}); + // } + + if (res.contains(key)) { + const e = res.getPtr(key) orelse unreachable; + e.* = .{ .min = @min(e.min, val), - .max = @max(e.min, val), + .max = @max(e.max, val), .sum = e.sum + val, .count = e.count + 1, }; } else { - gpr.value_ptr.* = .{ + const kd = try a.dupe(u8, key); + try res.put(kd,.{ .min = val, .max = val, .sum = val, .count = 1, - }; + }); } } @@ -103,14 +113,16 @@ fn run(a: std.mem.Allocator, infile: []const u8, t: *std.time.Timer) ![]const u8 try ww.writeAll("="); const v = nxt.value_ptr.*; const mm = @as(i32, v.min) - 999; - try std.fmt.format(ww, "{}.{}", .{@divFloor(mm ,10),@mod(mm, 10)}); + try std.fmt.format(ww, "{}.{}", .{@divTrunc(mm ,10),@abs(@rem(mm, 10))}); try ww.writeAll("/"); const mx = @as(i32, v.max) - 999; - try std.fmt.format(ww, "{}.{}", .{@divFloor(mx,10), @mod(mx, 10)}); + try std.fmt.format(ww, "{}.{}", .{@divTrunc(mx,10), @abs(@rem(mx, 10))}); try ww.writeAll("/"); - const me_a = v.sum / v.count; - const me = @as(i32, @intCast(me_a)) - 999; - try std.fmt.format(ww, "{}.{}", .{@divFloor(me ,10), @mod(me, 10)}); + const s_1 = v.sum / v.count; // mean + const s_2 = @as(i64, @intCast(s_1)) - 999; // shift + // std.log.warn("s_2 {}", .{s_2}); + try std.fmt.format(ww, "{}.{}", .{@divTrunc(s_2 ,10), @abs(@rem(s_2, 10))}); // scale + //try std.fmt.format(ww, " ct {} sum {}", .{v.count, v.sum}); try ww.writeAll(", "); } try ww.writeAll("}"); @@ -132,24 +144,30 @@ fn open_mmap(dir: std.fs.Dir, file_path: []const u8) ![]align(std.mem.page_size) return try std.os.mmap(null, stat.size, std.os.PROT.READ, std.os.MAP.PRIVATE, f.handle, 0); } -const test_input = -\\Hamburg;12.0 -\\Bulawayo;8.9 -\\Palembang;38.8 -\\St. John's;15.2 -\\Cracow;12.6 -\\Bridgetown;26.9 -\\Istanbul;6.2 -\\Roseau;34.4 -\\Conakry;31.2 -\\Istanbul;23.0 -; -const test_output = -\\{Bridgetown=26.9/26.9/26.9, Bulawayo=8.9/8.9/8.9, Conakry=31.2/31.2/31.2, Cracow=12.6/12.6/12.6, Hamburg=12.0/12.0/12.0, Istanbul=6.2/23.0/14.6, Palembang=38.8/38.8/38.8, Roseau=34.4/34.4/34.4, St. John's=15.2/15.2/15.2, } -; + test { + const test_input = + \\Hamburg;12.0 + \\Bulawayo;8.9 + \\Palembang;38.8 + \\St. John's;15.2 + \\Cracow;12.6 + \\Bridgetown;26.9 + \\Roseau;34.4 + \\Conakry;31.2 + \\Istanbul;23.0 + \\Istanbul;-3.0 + \\Istanbul;-9.0 + \\Istanbul;-10.0 + \\Istanbul;-15.0 + \\Istanbul;6.2 + ; + const test_output = + \\{Bridgetown=26.9/26.9/26.9, Bulawayo=8.9/8.9/8.9, Conakry=31.2/31.2/31.2, Cracow=12.6/12.6/12.6, Hamburg=12.0/12.0/12.0, Istanbul=-15.0/23.0/-1.3, Palembang=38.8/38.8/38.8, Roseau=34.4/34.4/34.4, St. John's=15.2/15.2/15.2, } + ; + var t = try std.time.Timer.start(); const a = std.testing.allocator; - const out = try run(a, test_input); + const out = try run(a, test_input, &t); defer a.free(out); try std.testing.expectEqualStrings(test_output, out); }