ReviewOS

also looking at this

zig-utils/zig-regex

Port to latest zig-master

#2
Closed armagidon-exception wants to merge main into main
53 files +1149 -1017
src/profiling.zigmodified+19-24
Changes to src/profiling.zig
@@ -1,15 +1,17 @@
11const std = ;
2const Clock = std.Io.Clock;
23
34/// Performance profiling and metrics tracking for regex operations
45pub const Profiler = struct {
56 allocator: std.mem.Allocator,
7 io: std.Io,
68 enabled: bool,
79 metrics: Metrics,
8 start_time: ?std.time.Instant,
10 start_time: ?std.Io.Timestamp,
911
1012 pub const Metrics = struct {
11 compilation_time_ns: u64 = 0,
12 match_time_ns: u64 = 0,
13 compilation_time_ns: i96 = 0,
14 match_time_ns: i96 = 0,
1315 match_count: usize = 0,
1416 nfa_states_created: usize = 0,
1517 backtrack_count: usize = 0,
@@ -25,13 +27,8 @@ pub const Profiler = struct {
2527
2628 pub fn format(
2729 self: Metrics,
28 comptime fmt: []const u8,
29 options: std.fmt.FormatOptions,
30 writer: anytype,
30 writer: *std.Io.Writer,
3131 ) !void {
32 _ = fmt;
33 _ = options;
34
3532 try writer.writeAll("\n=== Regex Performance Metrics ===\n");
3633 try writer.print("Compilation time: {d}μs\n", .{self.compilation_time_ns / 1000});
3734 try writer.print("Match time: {d}μs\n", .{self.match_time_ns / 1000});
@@ -49,41 +46,40 @@ pub const Profiler = struct {
4946 }
5047 };
5148
52 pub fn init(allocator: std.mem.Allocator, enabled: bool) Profiler {
49 pub fn init(allocator: std.mem.Allocator, io: std.Io, enabled: bool) Profiler {
5350 return .{
51 .io = io,
5452 .allocator = allocator,
5553 .enabled = enabled,
5654 .metrics = Metrics{},
57 .start_time = if (enabled) std.time.Instant.now() catch null else null,
55 .start_time = if (enabled) Clock.awake.now(io) else null,
5856 };
5957 }
6058
6159 /// Start timing a compilation phase
6260 pub fn startCompilation(self: *Profiler) void {
6361 if (!self.enabled) return;
64 self.start_time = std.time.Instant.now() catch null;
62 self.start_time = Clock.awake.now(self.io);
6563 }
6664
6765 /// End timing a compilation phase
6866 pub fn endCompilation(self: *Profiler) void {
6967 if (!self.enabled) return;
7068 const start = self.start_time orelse return;
71 const now = std.time.Instant.now() catch return;
72 self.metrics.compilation_time_ns += now.since(start);
69 self.metrics.compilation_time_ns += start.untilNow(self.io, Clock.awake).toNanoseconds();
7370 }
7471
7572 /// Start timing a match operation
7673 pub fn startMatch(self: *Profiler) void {
7774 if (!self.enabled) return;
78 self.start_time = std.time.Instant.now() catch null;
75 self.start_time = Clock.awake.now(self.io);
7976 }
8077
8178 /// End timing a match operation
8279 pub fn endMatch(self: *Profiler) void {
8380 if (!self.enabled) return;
8481 const start = self.start_time orelse return;
85 const now = std.time.Instant.now() catch return;
86 self.metrics.match_time_ns += now.since(start);
82 self.metrics.match_time_ns += start.untilNow(self.io, .awake).toNanoseconds();
8783 self.metrics.match_count += 1;
8884 }
8985
@@ -142,7 +138,7 @@ pub const Profiler = struct {
142138 /// Reset all metrics
143139 pub fn reset(self: *Profiler) void {
144140 self.metrics.reset();
145 self.start_time = if (self.enabled) std.time.Instant.now() catch null else null;
141 self.start_time = if (self.enabled) Clock.now(self.io) else null;
146142 }
147143
148144 /// Print metrics to stderr
@@ -156,7 +152,7 @@ pub const Profiler = struct {
156152pub const ScopedTimer = struct {
157153 profiler: *Profiler,
158154 timer_type: TimerType,
159 start: ?std.time.Instant,
155 start: ?std.Io.Timestamp,
160156
161157 pub const TimerType = enum {
162158 compilation,
@@ -167,15 +163,14 @@ pub const ScopedTimer = struct {
167163 return .{
168164 .profiler = profiler,
169165 .timer_type = timer_type,
170 .start = if (profiler.enabled) std.time.Instant.now() catch null else null,
166 .start = if (profiler.enabled) Clock.awake.now(profiler.io) else null,
171167 };
172168 }
173169
174170 pub fn deinit(self: *ScopedTimer) void {
175171 if (!self.profiler.enabled) return;
176172 const start = self.start orelse return;
177 const now = std.time.Instant.now() catch return;
178 const elapsed = now.since(start);
173 const elapsed = start.untilNow(self.profiler.io, Clock.awake).toNanoseconds();
179174 switch (self.timer_type) {
180175 .compilation => self.profiler.metrics.compilation_time_ns += elapsed,
181176 .match => {
@@ -188,7 +183,7 @@ pub const ScopedTimer = struct {
188183
189184test "profiler basic operations" {
190185 const allocator = std.testing.allocator;
191 var profiler = Profiler.init(allocator, true);
186 var profiler = Profiler.init(allocator, std.testing.io, true);
192187
193188 profiler.startCompilation();
194189 // Do some work (just loop to consume time)
@@ -210,7 +205,7 @@ test "profiler basic operations" {
210205
211206test "scoped timer" {
212207 const allocator = std.testing.allocator;
213 var profiler = Profiler.init(allocator, true);
208 var profiler = Profiler.init(allocator, std.testing.io, true);
214209
215210 {
216211 var timer = ScopedTimer.init(&profiler, .match);