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:
M | src/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);
}