ReviewOS

also looking at this

zig-utils/zig-regex

Migrate to zig 0.16

#5
Closed illya-laifu wants to merge zig-0.16-migrations into main
13 files +222 -239

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

benchmarks/prefix_optimization.zigmodified+43-45
Changes to benchmarks/prefix_optimization.zig
@@ -1,11 +1,7 @@
11const std = ;
22const Regex = .Regex;
33
4pub fn main() !void {
5 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
6 defer _ = gpa.deinit();
7 const allocator = gpa.allocator();
8
4pub fn main(init: std.process.Init) !void {
95 std.debug.print("=== Literal Prefix Optimization Benchmarks ===\n\n", .{});
106
117 // Create a long text where the pattern appears at the end
@@ -14,7 +10,7 @@ pub fn main() !void {
1410 // Test 1: Pattern with literal prefix (should use optimization)
1511 {
1612 std.debug.print("Test 1: Literal prefix optimization (FOUND_IT!)...\n", .{});
17 var regex = try Regex.compile(allocator, "FOUND_IT!");
13 var regex = try Regex.compile(init.gpa, "FOUND_IT!");
1814 defer regex.deinit();
1915
2016 // Print optimization info
@@ -24,31 +20,32 @@ pub fn main() !void {
2420 std.debug.print(" ✗ No literal prefix found\n", .{});
2521 }
2622
27 var timer = try std.time.Timer.start();
28 const start = timer.read();
23 const start = std.Io.Timestamp.now(init.io, .real);
2924
3025 const iterations: usize = 10000;
3126 var i: usize = 0;
3227 while (i < iterations) : (i += 1) {
3328 if (try regex.find(long_text)) |match| {
3429 var mut_match = match;
35 mut_match.deinit(allocator);
30 mut_match.deinit(init.gpa);
3631 }
3732 }
3833
39 const elapsed = timer.read() - start;
40 const avg_ns = elapsed / iterations;
34 const end = std.Io.Timestamp.now(init.io, .real);
35 const elapsed = start.durationTo(end);
36 const avg_ns = @divTrunc(elapsed.nanoseconds, iterations);
37
4138 std.debug.print(" {d} iterations in {d:.2}ms ({d:.2}µs/op)\n\n", .{
4239 iterations,
43 @as(f64, @floatFromInt(elapsed)) / 1_000_000.0,
44 @as(f64, @floatFromInt(avg_ns)) / 1000.0,
40 @as(f64, @floatFromInt(elapsed.toMilliseconds())),
41 @as(f64, @floatFromInt(avg_ns)) / std.time.us_per_ms,
4542 });
4643 }
4744
4845 // Test 2: Pattern without useful prefix (no optimization) - using fewer iterations
4946 {
5047 std.debug.print("Test 2: No prefix optimization (.*FOUND)...\n", .{});
51 var regex = try Regex.compile(allocator, ".*FOUND");
48 var regex = try Regex.compile(init.gpa, ".*FOUND");
5249 defer regex.deinit();
5350
5451 if (regex.opt_info.literal_prefix) |prefix| {
@@ -57,8 +54,7 @@ pub fn main() !void {
5754 std.debug.print(" ✗ No literal prefix found (slower performance expected)\n", .{});
5855 }
5956
60 var timer = try std.time.Timer.start();
61 const start = timer.read();
57 const start = std.Io.Timestamp.now(init.io, .real);
6258
6359 // Use fewer iterations since this is much slower without optimization
6460 const iterations: usize = 100;
@@ -66,16 +62,18 @@ pub fn main() !void {
6662 while (i < iterations) : (i += 1) {
6763 if (try regex.find(long_text)) |match| {
6864 var mut_match = match;
69 mut_match.deinit(allocator);
65 mut_match.deinit(init.gpa);
7066 }
7167 }
7268
73 const elapsed = timer.read() - start;
74 const avg_ns = elapsed / iterations;
69 const end = std.Io.Timestamp.now(init.io, .real);
70 const elapsed = start.durationTo(end);
71 const avg_ns = @divTrunc(elapsed.nanoseconds, iterations);
72
7573 std.debug.print(" {d} iterations in {d:.2}ms ({d:.2}µs/op)\n\n", .{
7674 iterations,
77 @as(f64, @floatFromInt(elapsed)) / 1_000_000.0,
78 @as(f64, @floatFromInt(avg_ns)) / 1000.0,
75 @as(f64, @floatFromInt(elapsed.toMilliseconds())),
76 @as(f64, @floatFromInt(avg_ns)) / std.time.us_per_ms,
7977 });
8078 }
8179
@@ -83,7 +81,7 @@ pub fn main() !void {
8381 {
8482 std.debug.print("Test 3: Prefix with complex suffix (hello.*world)...\n", .{});
8583 const text_with_hello = "blah blah " ** 50 ++ "hello there world";
86 var regex = try Regex.compile(allocator, "hello.*world");
84 var regex = try Regex.compile(init.gpa, "hello.*world");
8785 defer regex.deinit();
8886
8987 if (regex.opt_info.literal_prefix) |prefix| {
@@ -92,31 +90,31 @@ pub fn main() !void {
9290 std.debug.print(" ✗ No literal prefix found\n", .{});
9391 }
9492
95 var timer = try std.time.Timer.start();
96 const start = timer.read();
93 const start = std.Io.Timestamp.now(init.io, .real);
9794
9895 const iterations: usize = 10000;
9996 var i: usize = 0;
10097 while (i < iterations) : (i += 1) {
10198 if (try regex.find(text_with_hello)) |match| {
10299 var mut_match = match;
103 mut_match.deinit(allocator);
100 mut_match.deinit(init.gpa);
104101 }
105102 }
106103
107 const elapsed = timer.read() - start;
108 const avg_ns = elapsed / iterations;
104 const end = std.Io.Timestamp.now(init.io, .real);
105 const elapsed = start.durationTo(end);
106 const avg_ns = @divTrunc(elapsed.nanoseconds, iterations);
109107 std.debug.print(" {d} iterations in {d:.2}ms ({d:.2}µs/op)\n\n", .{
110108 iterations,
111 @as(f64, @floatFromInt(elapsed)) / 1_000_000.0,
112 @as(f64, @floatFromInt(avg_ns)) / 1000.0,
109 @as(f64, @floatFromInt(elapsed.toMilliseconds())),
110 @as(f64, @floatFromInt(avg_ns)) / std.time.us_per_ms,
113111 });
114112 }
115113
116114 // Test 4: Anchored patterns
117115 {
118116 std.debug.print("Test 4: Start-anchored pattern (^hello)...\n", .{});
119 var regex = try Regex.compile(allocator, "^hello");
117 var regex = try Regex.compile(init.gpa, "^hello");
120118 defer regex.deinit();
121119
122120 if (regex.opt_info.anchored_start) {
@@ -127,8 +125,7 @@ pub fn main() !void {
127125 }
128126
129127 const text = "hello world";
130 var timer = try std.time.Timer.start();
131 const start = timer.read();
128 const start = std.Io.Timestamp.now(init.io, .real);
132129
133130 const iterations: usize = 10000;
134131 var i: usize = 0;
@@ -136,12 +133,13 @@ pub fn main() !void {
136133 _ = try regex.isMatch(text);
137134 }
138135
139 const elapsed = timer.read() - start;
140 const avg_ns = elapsed / iterations;
136 const end = std.Io.Timestamp.now(init.io, .real);
137 const elapsed = start.durationTo(end);
138 const avg_ns = @divTrunc(elapsed.nanoseconds, iterations);
141139 std.debug.print(" {d} iterations in {d:.2}ms ({d:.2}µs/op)\n\n", .{
142140 iterations,
143 @as(f64, @floatFromInt(elapsed)) / 1_000_000.0,
144 @as(f64, @floatFromInt(avg_ns)) / 1000.0,
141 @as(f64, @floatFromInt(elapsed.toMilliseconds())),
142 @as(f64, @floatFromInt(avg_ns)) / std.time.us_per_ms,
145143 });
146144 }
147145
@@ -149,31 +147,31 @@ pub fn main() !void {
149147 {
150148 std.debug.print("Test 5: Email pattern (user@example.com)...\n", .{});
151149 const email_text = "Contact us at " ++ ("some filler text here. " ** 20) ++ "user@example.com for support";
152 var regex = try Regex.compile(allocator, "user@example.com");
150 var regex = try Regex.compile(init.gpa, "user@example.com");
153151 defer regex.deinit();
154152
155153 if (regex.opt_info.literal_prefix) |prefix| {
156 std.debug.print(" ✓ Using literal prefix: \"{s}\" (min_len={d})\n", .{prefix, regex.opt_info.min_length});
154 std.debug.print(" ✓ Using literal prefix: \"{s}\" (min_len={d})\n", .{ prefix, regex.opt_info.min_length });
157155 }
158156
159 var timer = try std.time.Timer.start();
160 const start = timer.read();
157 const start = std.Io.Timestamp.now(init.io, .real);
161158
162159 const iterations: usize = 10000;
163160 var i: usize = 0;
164161 while (i < iterations) : (i += 1) {
165162 if (try regex.find(email_text)) |match| {
166163 var mut_match = match;
167 mut_match.deinit(allocator);
164 mut_match.deinit(init.gpa);
168165 }
169166 }
170167
171 const elapsed = timer.read() - start;
172 const avg_ns = elapsed / iterations;
168 const end = std.Io.Timestamp.now(init.io, .real);
169 const elapsed = start.durationTo(end);
170 const avg_ns = @divTrunc(elapsed.nanoseconds, iterations);
173171 std.debug.print(" {d} iterations in {d:.2}ms ({d:.2}µs/op)\n\n", .{
174172 iterations,
175 @as(f64, @floatFromInt(elapsed)) / 1_000_000.0,
176 @as(f64, @floatFromInt(avg_ns)) / 1000.0,
173 @as(f64, @floatFromInt(elapsed.toMilliseconds())),
174 @as(f64, @floatFromInt(avg_ns)) / std.time.us_per_ms,
177175 });
178176 }
179177