6986eef7
Add BaselineRecord + JSON round-trip for frame stats
a73x 2026-04-17 15:28
Lays the foundation for bench-baseline / bench-check tooling (Task 10). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
diff --git a/src/bench_stats.zig b/src/bench_stats.zig index dd14c67..457ee79 100644 --- a/src/bench_stats.zig +++ b/src/bench_stats.zig @@ -200,3 +200,68 @@ test "FrameTimingStats handles empty ring" { try std.testing.expectEqual(@as(usize, 0), stats.frame_count); try std.testing.expectEqual(@as(u32, 0), stats.snapshot.min); } pub const BaselineRecord = struct { workload_sha: []const u8, zig_version: []const u8, waystty_sha: []const u8, frame_count: usize, sections: struct { snapshot: SectionStats, row_rebuild: SectionStats, atlas_upload: SectionStats, instance_upload: SectionStats, gpu_submit: SectionStats, }, }; /// Serialize `rec` to JSON and return an owned slice. Caller must free. pub fn writeBaselineJson(alloc: std.mem.Allocator, rec: BaselineRecord) ![]u8 { var out: std.Io.Writer.Allocating = .init(alloc); errdefer out.deinit(); try std.json.Stringify.value(rec, .{ .whitespace = .indent_2 }, &out.writer); return out.toOwnedSlice(); } pub fn readBaselineJson(alloc: std.mem.Allocator, bytes: []const u8) !BaselineRecord { var parsed = try std.json.parseFromSlice(BaselineRecord, alloc, bytes, .{}); defer parsed.deinit(); return .{ .workload_sha = try alloc.dupe(u8, parsed.value.workload_sha), .zig_version = try alloc.dupe(u8, parsed.value.zig_version), .waystty_sha = try alloc.dupe(u8, parsed.value.waystty_sha), .frame_count = parsed.value.frame_count, .sections = parsed.value.sections, }; } test "baseline JSON round-trip" { const alloc = std.testing.allocator; const rec = BaselineRecord{ .workload_sha = "abcdef", .zig_version = "0.15.0", .waystty_sha = "123abc", .frame_count = 256, .sections = .{ .snapshot = .{ .min = 1, .avg = 2, .p99 = 3, .max = 4 }, .row_rebuild = .{ .min = 10, .avg = 20, .p99 = 30, .max = 40 }, .atlas_upload = .{ .min = 0, .avg = 0, .p99 = 0, .max = 0 }, .instance_upload = .{ .min = 5, .avg = 6, .p99 = 7, .max = 8 }, .gpu_submit = .{ .min = 9, .avg = 9, .p99 = 9, .max = 9 }, }, }; const json_bytes = try writeBaselineJson(alloc, rec); defer alloc.free(json_bytes); const parsed = try readBaselineJson(alloc, json_bytes); defer { alloc.free(parsed.workload_sha); alloc.free(parsed.zig_version); alloc.free(parsed.waystty_sha); } try std.testing.expectEqual(@as(usize, 256), parsed.frame_count); try std.testing.expectEqual(@as(u32, 30), parsed.sections.row_rebuild.p99); try std.testing.expectEqualStrings("abcdef", parsed.workload_sha); }