diff --git a/README.md b/README.md index 90972c5..3901765 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,22 @@ The Zig Discord server is plagued with modern scum, of course, modern scum will On different note, I defend simplicity and minimalism, so I am not saying that *every* Zig developer who thinks differently is scum, I just say that if you cannot think beyond your viewpoint you will reach nowhere. Lastly, if your software is not straightforward and simple to use, then why criticising someone for now knowing how to use it? The only reasonable way to make software complicated is as long as user friendliness is not a tradeoff for performance or minimalism. ### benchmark for the nerds -As you can see both run as fast as the other + +first benchmark is 2 runs and aether is allocating twice, for storing data, and for displaying data in hashmaps and array lists | Benchmark | Runs | Total Time | Time/Run (Avg ± σ) | Range (Min ... Max) | p75 | p99 | p995 | |-------------------|------|------------|-------------------------|-----------------------------|-----------|-----------|-----------| | aether | 2 | 1m14.271s | 37.135s ± 960.345ms | (36.456s ... 37.814s) | 37.814s | 37.814s | 37.814s | | aether [MEMORY] | | | 54.095MiB ± 0B | (54.095MiB ... 54.095MiB) | 54.095MiB | 54.095MiB | 54.095MiB | | std.json | 2 | 1m12.731s | 36.365s ± 621.288ms | (35.926s ... 36.805s) | 36.805s | 36.805s | 36.805s | | std.json [MEMORY] | | | 43.420MiB ± 0B | (43.420MiB ... 43.420MiB) | 43.420MiB | 43.420MiB | 43.420MiB | + +this is 1 run of the code located in `benchmarks/main.zig`, as you can see aether is drastically more efficient +| Benchmark | Runs | Total Time | Time/Run (avg ± σ) | (min ... max) | p75 | p99 | p995 | +|-------------------|------|------------|--------------------|--------------------------|----------|----------|----------| +| aether | 1 | 29.435s | 29.435s ± 0ns | (29.435s ... 29.435s) | 29.435s | 29.435s | 29.435s | +| aether [MEMORY] | | | 42.393MiB ± 0B | (42.393MiB ... 42.393MiB)| 42.393MiB| 42.393MiB| 42.393MiB| +| std.json | 1 | 34.889s | 34.889s ± 0ns | (34.889s ... 34.889s) | 34.889s | 34.889s | 34.889s | +| std.json [MEMORY] | | | 43.420MiB ± 0B | (43.420MiB ... 43.420MiB)| 43.420MiB| 43.420MiB| 43.420MiB| + +memory wise, aether is not much bigger, it's basically equal to std.json +I presume that the time that aether takes running is because of SIMD, but I can't be sure diff --git a/benchmarks/Benchmark Results.md b/benchmarks/Benchmark Results.md new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/main.zig b/benchmarks/main.zig index eb43319..2124cf1 100644 --- a/benchmarks/main.zig +++ b/benchmarks/main.zig @@ -10,34 +10,25 @@ fn aetherbenchAux(allocator: std.mem.Allocator) !void { const Language = aether.Language; var tokenizer: Tokenizer = try .init(allocator, bigdata); - errdefer tokenizer.deinit(allocator); + defer tokenizer.deinit(allocator); - var self = try allocator.create(Language); - self.* = Language.init; - defer allocator.destroy(self); - defer self.deinit(allocator); + var self = Language.init; - const idx: usize = try self.parse(allocator, &tokenizer); - - var root = try self.getValue(allocator, idx); - defer root.deinit(allocator); + // we use a better storing strategy + const idx: usize = try Language.parse(&self, allocator, &tokenizer); + const root = self.index.get(idx); try std.testing.expect(root == .object); - //std.debug.print("{}\n", .{root}); } fn stdjsonbenchAux(allocator: std.mem.Allocator) !void { + // taken from https://github.com/ziglang/zig/blob/9d534790ebc869ec933e932abe4be8b9e3593bbc/lib/std/json/dynamic_test.zig#L20 + // and modified to use a 10mb file + // 2025-06-05 const json = std.json; - - const root = try json.parseFromSliceLeaky(json.Value, allocator, bigdata, .{ - .allocate = .alloc_always, - .duplicate_field_behavior = .@"error", - .max_value_len = 4096, - .ignore_unknown_fields = true, - }); + const root = try json.parseFromSliceLeaky(json.Value, allocator, bigdata, .{}); try std.testing.expect(root == .object); - //std.debug.print("{}\n", .{root}); } pub fn aetherbench(allocator: std.mem.Allocator) void { @@ -54,14 +45,9 @@ pub fn main() !void { const allocator = gpa.allocator(); var bench = zbench.Benchmark.init(allocator, .{ - .iterations = 2, + .iterations = 1, }); - defer { - bench.deinit(); - const deinit_status = gpa.deinit(); - if (deinit_status == .leak) - std.debug.panic("Memory leak detected", .{}); - } + defer bench.deinit(); try bench.add("aether", &aetherbench, .{ .track_allocations = true, @@ -71,19 +57,13 @@ pub fn main() !void { }); try stdout.writeByte('\n'); - try bench.run(stdout); - - try stdout.writeAll("["); + try zbench.prettyPrintHeader(stdout); var iter = try bench.iterator(); - var i: usize = 0; while (try iter.next()) |step| switch (step) { .progress => |_| {}, .result => |x| { defer x.deinit(); - defer i += 1; - if (0 < i) try stdout.writeAll(", "); - try x.writeJSON(gpa.allocator(), stdout); + try x.prettyPrint(allocator, stdout, true); }, }; - try stdout.writeAll("]\n"); } diff --git a/tokenizer.zig b/tokenizer.zig index 71e749e..d0a92e4 100644 --- a/tokenizer.zig +++ b/tokenizer.zig @@ -53,8 +53,9 @@ frame: usize, /// Initialize a new tokenizer pub fn init(allocator: mem.Allocator, text: []const u8) mem.Allocator.Error!Self { - const stack = try allocator.alloc(usize, 4096); - @memset(stack, 0); + const initial_stack_size = @min(32, text.len / 16 + 1); + const stack = try allocator.alloc(usize, initial_stack_size); + stack[0] = 0; return .{ .text = text, diff --git a/zig-out/bin/benchmarks b/zig-out/bin/benchmarks index 7be809e..de8e671 100755 Binary files a/zig-out/bin/benchmarks and b/zig-out/bin/benchmarks differ