lib/bench/src/metadata.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const builtin = @import("builtin");
3 const pretty_json = @import("pretty").json;
4 const stabilizer = @import("stabilizer");
5
6 pub const BuildMetadata = struct {
7 git_sha: []const u8,
8 git_dirty: bool,
9 optimize: []const u8,
10 target: []const u8,
11 zig_version: []const u8,
12 host_os: []const u8,
13 host_arch: []const u8,
14 };
15
16 const FakeBuildOptions = struct {
17 const git_sha = "abc123";
18 const git_dirty = true;
19 const optimize = "ReleaseFast";
20 const target = "x86_64-linux-gnu";
21 const host_os = "linux";
22 const host_arch = "x86_64";
23 };
24
25 pub fn currentBuildMetadata(comptime build_options: type) BuildMetadata {
26 return .{
27 .git_sha = build_options.git_sha,
28 .git_dirty = build_options.git_dirty,
29 .optimize = build_options.optimize,
30 .target = build_options.target,
31 .zig_version = builtin.zig_version_string,
32 .host_os = build_options.host_os,
33 .host_arch = build_options.host_arch,
34 };
35 }
36
37 pub fn compiledBuildMetadata() BuildMetadata {
38 return .{
39 .git_sha = "",
40 .git_dirty = false,
41 .optimize = @tagName(builtin.mode),
42 .target = @tagName(builtin.cpu.arch) ++ "-" ++ @tagName(builtin.os.tag) ++ "-" ++ @tagName(builtin.abi),
43 .zig_version = builtin.zig_version_string,
44 .host_os = @tagName(builtin.os.tag),
45 .host_arch = @tagName(builtin.cpu.arch),
46 };
47 }
48
49 pub fn writeBuildMetadata(object: pretty_json.Object, metadata: BuildMetadata) !void {
50 try object.field("git_sha", metadata.git_sha);
51 try object.field("git_dirty", metadata.git_dirty);
52 try object.field("optimize", metadata.optimize);
53 try object.field("target", metadata.target);
54 try object.field("zig_version", metadata.zig_version);
55 try object.field("host_os", metadata.host_os);
56 try object.field("host_arch", metadata.host_arch);
57 try object.end();
58 }
59
60 pub fn writeStabilizerConfig(object: pretty_json.Object, layout_config: stabilizer.Config) !void {
61 try object.field("seed", layout_config.seed);
62 const heap = try object.object("heap");
63 try heap.field("enabled", layout_config.heap.enabled);
64 try heap.field("pointer_validation", layout_config.heap.pointer_validation);
65 try heap.field("shuffle_slots", layout_config.heap.shuffle_slots);
66 try heap.field("min_class_size", layout_config.heap.min_class_size);
67 try heap.field("max_shuffled_size", layout_config.heap.max_shuffled_size);
68 try heap.end();
69 const stack = try object.object("stack");
70 try stack.field("enabled", layout_config.stack.enabled);
71 try stack.field("entries", layout_config.stack.entries);
72 try stack.field("alignment", layout_config.stack.alignment);
73 try stack.end();
74 const code = try object.object("code");
75 try code.field("enabled", layout_config.code.enabled);
76 try code.field("shuffle_slots", layout_config.code.shuffle_slots);
77 try code.field("alignment", layout_config.code.alignment);
78 try code.field("interval_ms", layout_config.code.interval_ms);
79 try code.end();
80 try object.end();
81 }
82
83 test "stabilizer config metadata records heap stack and code fields" {
84 const allocator = std.testing.allocator;
85 var out = std.Io.Writer.Allocating.init(allocator);
86 defer out.deinit();
87
88 var stream = pretty_json.Writer.init(&out.writer, .minified);
89 try writeStabilizerConfig(try stream.object(), .{
90 .seed = 77,
91 .heap = .{
92 .pointer_validation = false,
93 .shuffle_slots = 5,
94 .max_shuffled_size = 4096,
95 },
96 .stack = .{
97 .entries = 9,
98 },
99 .code = .{
100 .enabled = false,
101 },
102 });
103
104 const json = out.written();
105 try std.testing.expect(std.mem.indexOf(u8, json, "\"seed\":77") != null);
106 try std.testing.expect(std.mem.indexOf(u8, json, "\"pointer_validation\":false") != null);
107 try std.testing.expect(std.mem.indexOf(u8, json, "\"shuffle_slots\":5") != null);
108 try std.testing.expect(std.mem.indexOf(u8, json, "\"max_shuffled_size\":4096") != null);
109 try std.testing.expect(std.mem.indexOf(u8, json, "\"stack\":{\"enabled\":true,\"entries\":9") != null);
110 try std.testing.expect(std.mem.indexOf(u8, json, "\"code\":{\"enabled\":false") != null);
111 }
112
113 test "build metadata helper records profile build options" {
114 const value = currentBuildMetadata(FakeBuildOptions);
115 try std.testing.expectEqualStrings("abc123", value.git_sha);
116 try std.testing.expect(value.git_dirty);
117 try std.testing.expectEqualStrings("ReleaseFast", value.optimize);
118 try std.testing.expectEqualStrings("x86_64-linux-gnu", value.target);
119 try std.testing.expectEqualStrings(builtin.zig_version_string, value.zig_version);
120 try std.testing.expectEqualStrings("linux", value.host_os);
121 try std.testing.expectEqualStrings("x86_64", value.host_arch);
122 }
123
124 test "build metadata writes benchmark environment" {
125 var out = std.Io.Writer.Allocating.init(std.testing.allocator);
126 defer out.deinit();
127
128 var stream = pretty_json.Writer.init(&out.writer, .minified);
129 const root = try stream.object();
130 try writeBuildMetadata(try root.object("metadata"), .{
131 .git_sha = "abc123",
132 .git_dirty = true,
133 .optimize = "ReleaseFast",
134 .target = "x86_64-linux-gnu",
135 .zig_version = "0.16.0",
136 .host_os = "linux",
137 .host_arch = "x86_64",
138 });
139 try root.end();
140
141 const json = out.written();
142 try std.testing.expect(std.mem.indexOf(u8, json, "\"metadata\":{") != null);
143 try std.testing.expect(std.mem.indexOf(u8, json, "\"git_sha\":\"abc123\"") != null);
144 try std.testing.expect(std.mem.indexOf(u8, json, "\"git_dirty\":true") != null);
145 try std.testing.expect(std.mem.indexOf(u8, json, "\"host_os\":\"linux\"") != null);
146 }