Skip to content

Commit bd20e92

Browse files
committed
chore: wip
1 parent 81c47d7 commit bd20e92

12 files changed

Lines changed: 1253 additions & 63 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/.zig-cache
2+
/zig-out

build.zig

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,27 @@ pub fn build(b: *std.Build) void {
99
.root_source_file = b.path("src/bench.zig"),
1010
});
1111

12+
// Create modules for advanced features
13+
const export_module = b.createModule(.{
14+
.root_source_file = b.path("src/export.zig"),
15+
});
16+
export_module.addImport("bench", bench_module);
17+
18+
const comparison_module = b.createModule(.{
19+
.root_source_file = b.path("src/comparison.zig"),
20+
});
21+
comparison_module.addImport("bench", bench_module);
22+
23+
const memory_profiler_module = b.createModule(.{
24+
.root_source_file = b.path("src/memory_profiler.zig"),
25+
});
26+
27+
const ci_module = b.createModule(.{
28+
.root_source_file = b.path("src/ci.zig"),
29+
});
30+
ci_module.addImport("bench", bench_module);
31+
ci_module.addImport("comparison", comparison_module);
32+
1233
// Example executables
1334
const examples = [_]struct {
1435
name: []const u8,
@@ -17,6 +38,9 @@ pub fn build(b: *std.Build) void {
1738
.{ .name = "basic", .path = "examples/basic.zig" },
1839
.{ .name = "async", .path = "examples/async.zig" },
1940
.{ .name = "custom_options", .path = "examples/custom_options.zig" },
41+
.{ .name = "filtering_baseline", .path = "examples/filtering_baseline.zig" },
42+
.{ .name = "allocators", .path = "examples/allocators.zig" },
43+
.{ .name = "advanced_features", .path = "examples/advanced_features.zig" },
2044
};
2145

2246
inline for (examples) |example| {
@@ -27,6 +51,14 @@ pub fn build(b: *std.Build) void {
2751
});
2852
exe_module.addImport("bench", bench_module);
2953

54+
// Add advanced feature imports for advanced_features example
55+
if (std.mem.eql(u8, example.name, "advanced_features")) {
56+
exe_module.addImport("export", export_module);
57+
exe_module.addImport("comparison", comparison_module);
58+
exe_module.addImport("memory_profiler", memory_profiler_module);
59+
exe_module.addImport("ci", ci_module);
60+
}
61+
3062
const exe = b.addExecutable(.{
3163
.name = example.name,
3264
.root_module = exe_module,
@@ -58,6 +90,14 @@ pub fn build(b: *std.Build) void {
5890
});
5991
exe_module.addImport("bench", bench_module);
6092

93+
// Add advanced feature imports for advanced_features example
94+
if (std.mem.eql(u8, example.name, "advanced_features")) {
95+
exe_module.addImport("export", export_module);
96+
exe_module.addImport("comparison", comparison_module);
97+
exe_module.addImport("memory_profiler", memory_profiler_module);
98+
exe_module.addImport("ci", ci_module);
99+
}
100+
61101
const exe = b.addExecutable(.{
62102
.name = example.name,
63103
.root_module = exe_module,

examples/advanced_features.zig

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
const std = @import("std");
2+
const bench = @import("bench");
3+
4+
// Import the advanced features
5+
const export_mod = @import("export");
6+
const comparison_mod = @import("comparison");
7+
const memory_profiler = @import("memory_profiler");
8+
const ci = @import("ci");
9+
10+
var global_sum: u64 = 0;
11+
12+
fn fastBenchmark() void {
13+
var sum: u64 = 0;
14+
var i: u32 = 0;
15+
while (i < 100) : (i += 1) {
16+
sum += i;
17+
}
18+
global_sum = sum;
19+
}
20+
21+
fn mediumBenchmark() void {
22+
var sum: u64 = 0;
23+
var i: u32 = 0;
24+
while (i < 1_000) : (i += 1) {
25+
sum += i;
26+
}
27+
global_sum = sum;
28+
}
29+
30+
fn slowBenchmark() void {
31+
var sum: u64 = 0;
32+
var i: u32 = 0;
33+
while (i < 10_000) : (i += 1) {
34+
sum += i;
35+
}
36+
global_sum = sum;
37+
}
38+
39+
fn memoryIntensiveBenchmark(allocator: std.mem.Allocator) void {
40+
var list = std.ArrayList(u64){};
41+
defer list.deinit(allocator);
42+
43+
var i: usize = 0;
44+
while (i < 1000) : (i += 1) {
45+
list.append(allocator, i) catch unreachable;
46+
}
47+
global_sum = list.items.len;
48+
}
49+
50+
pub fn main() !void {
51+
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
52+
defer _ = gpa.deinit();
53+
const allocator = gpa.allocator();
54+
55+
// Run benchmarks
56+
var suite = bench.BenchmarkSuite.init(allocator);
57+
defer suite.deinit();
58+
59+
try suite.add("Fast Benchmark", fastBenchmark);
60+
try suite.add("Medium Benchmark", mediumBenchmark);
61+
try suite.add("Slow Benchmark", slowBenchmark);
62+
63+
std.debug.print("\n{s}=== Running Benchmarks ==={s}\n", .{ bench.Formatter.BOLD, bench.Formatter.RESET });
64+
try suite.run();
65+
66+
// Note: We can't easily access the results from suite.run(), so we'll run them again
67+
// In a real implementation, you'd modify BenchmarkSuite.run() to return results
68+
var results = std.ArrayList(bench.BenchmarkResult){};
69+
defer {
70+
for (results.items) |*result| {
71+
result.deinit();
72+
}
73+
results.deinit(allocator);
74+
}
75+
76+
for (suite.benchmarks.items) |*benchmark| {
77+
const result = try benchmark.run(allocator);
78+
try results.append(allocator, result);
79+
}
80+
81+
// 1. Export to JSON
82+
std.debug.print("\n{s}=== Exporting Results ==={s}\n", .{ bench.Formatter.BOLD, bench.Formatter.RESET });
83+
const exporter = export_mod.Exporter.init(allocator);
84+
try exporter.exportToFile(results.items, "benchmark_results.json", .json);
85+
std.debug.print("✓ Exported to JSON: benchmark_results.json\n", .{});
86+
87+
// 2. Export to CSV
88+
try exporter.exportToFile(results.items, "benchmark_results.csv", .csv);
89+
std.debug.print("✓ Exported to CSV: benchmark_results.csv\n", .{});
90+
91+
// 3. Compare with baseline (if exists)
92+
std.debug.print("\n{s}=== Baseline Comparison ==={s}\n", .{ bench.Formatter.BOLD, bench.Formatter.RESET });
93+
94+
const baseline_exists = blk: {
95+
std.fs.cwd().access("baseline.json", .{}) catch break :blk false;
96+
break :blk true;
97+
};
98+
99+
if (baseline_exists) {
100+
const comparator = comparison_mod.Comparator.init(allocator, 10.0);
101+
const comparisons = try comparator.compare(results.items, "baseline.json");
102+
defer allocator.free(comparisons);
103+
104+
const stdout = std.fs.File.stdout();
105+
try comparator.printComparison(stdout, comparisons);
106+
} else {
107+
std.debug.print("No baseline found. Run with baseline.json to enable comparison.\n", .{});
108+
std.debug.print("Creating baseline from current results...\n", .{});
109+
try exporter.exportToFile(results.items, "baseline.json", .json);
110+
std.debug.print("✓ Baseline created: baseline.json\n", .{});
111+
}
112+
113+
// 4. Memory Profiling Demo
114+
std.debug.print("\n{s}=== Memory Profiling Demo ==={s}\n", .{ bench.Formatter.BOLD, bench.Formatter.RESET });
115+
116+
var profiling_allocator = memory_profiler.ProfilingAllocator.init(allocator);
117+
const tracked_allocator = profiling_allocator.allocator();
118+
119+
// Run a memory-intensive benchmark
120+
var timer = try std.time.Timer.start();
121+
memoryIntensiveBenchmark(tracked_allocator);
122+
const elapsed = timer.read();
123+
124+
const mem_result = memory_profiler.MemoryBenchmarkResult{
125+
.name = "Memory Intensive Benchmark",
126+
.time_ns = @floatFromInt(elapsed),
127+
.memory_stats = profiling_allocator.getStats(),
128+
};
129+
130+
const stdout = std.fs.File.stdout();
131+
try mem_result.print(stdout);
132+
133+
// 5. CI/CD Integration Demo
134+
std.debug.print("\n{s}=== CI/CD Integration Demo ==={s}\n", .{ bench.Formatter.BOLD, bench.Formatter.RESET });
135+
136+
const ci_format = ci.detectCIEnvironment();
137+
std.debug.print("Detected CI environment: {s}\n", .{@tagName(ci_format)});
138+
139+
var ci_helper = ci.CIHelper.init(allocator, .{
140+
.fail_on_regression = true,
141+
.regression_threshold = 10.0,
142+
.baseline_path = if (baseline_exists) "baseline.json" else null,
143+
.output_format = ci_format,
144+
});
145+
146+
try ci_helper.generateSummary(results.items);
147+
148+
if (baseline_exists) {
149+
const has_regression = try ci_helper.checkRegressions(results.items);
150+
if (has_regression and ci_helper.shouldFailBuild(has_regression)) {
151+
std.debug.print("\n{s}⚠️ Build would fail due to performance regressions{s}\n", .{ bench.Formatter.YELLOW, bench.Formatter.RESET });
152+
// In CI, you would: std.process.exit(1);
153+
}
154+
}
155+
156+
std.debug.print("\n{s}✓ Advanced features demo complete!{s}\n", .{ bench.Formatter.GREEN, bench.Formatter.RESET });
157+
}

examples/allocators.zig

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
const std = @import("std");
2+
const bench = @import("bench");
3+
4+
var global_result: usize = 0;
5+
6+
// Benchmark function that uses the provided allocator
7+
fn benchWithPageAllocator(allocator: std.mem.Allocator) void {
8+
var list = std.ArrayList(u64){};
9+
defer list.deinit(allocator);
10+
11+
var i: usize = 0;
12+
while (i < 1000) : (i += 1) {
13+
list.append(allocator, i) catch unreachable;
14+
}
15+
global_result = list.items.len;
16+
}
17+
18+
fn benchWithGPA(allocator: std.mem.Allocator) void {
19+
var list = std.ArrayList(u64){};
20+
defer list.deinit(allocator);
21+
22+
var i: usize = 0;
23+
while (i < 1000) : (i += 1) {
24+
list.append(allocator, i) catch unreachable;
25+
}
26+
global_result = list.items.len;
27+
}
28+
29+
fn benchWithArena(allocator: std.mem.Allocator) void {
30+
var list = std.ArrayList(u64){};
31+
defer list.deinit(allocator);
32+
33+
var i: usize = 0;
34+
while (i < 1000) : (i += 1) {
35+
list.append(allocator, i) catch unreachable;
36+
}
37+
global_result = list.items.len;
38+
}
39+
40+
fn benchHashMapOperations(allocator: std.mem.Allocator) void {
41+
var map = std.AutoHashMap(u32, u32).init(allocator);
42+
defer map.deinit();
43+
44+
var i: u32 = 0;
45+
while (i < 500) : (i += 1) {
46+
map.put(i, i * 2) catch unreachable;
47+
}
48+
49+
var sum: u32 = 0;
50+
i = 0;
51+
while (i < 500) : (i += 1) {
52+
sum += map.get(i) orelse 0;
53+
}
54+
global_result = sum;
55+
}
56+
57+
pub fn main() !void {
58+
// Create different allocators
59+
const page_allocator = std.heap.page_allocator;
60+
61+
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
62+
defer _ = gpa.deinit();
63+
const gpa_allocator = gpa.allocator();
64+
65+
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
66+
defer arena.deinit();
67+
const arena_allocator = arena.allocator();
68+
69+
// Suite with page allocator
70+
{
71+
var suite = bench.BenchmarkSuite.init(page_allocator);
72+
defer suite.deinit();
73+
74+
try suite.addWithAllocator("ArrayList (PageAllocator)", benchWithPageAllocator);
75+
try suite.addWithAllocator("HashMap (PageAllocator)", benchHashMapOperations);
76+
77+
const stdout = std.fs.File.stdout();
78+
var buf: [256]u8 = undefined;
79+
const msg = try std.fmt.bufPrint(&buf, "\n{s}[PageAllocator]{s}\n", .{ bench.Formatter.CYAN, bench.Formatter.RESET });
80+
try stdout.writeAll(msg);
81+
82+
try suite.run();
83+
}
84+
85+
// Suite with GPA
86+
{
87+
var suite = bench.BenchmarkSuite.init(gpa_allocator);
88+
defer suite.deinit();
89+
90+
try suite.addWithAllocator("ArrayList (GPA)", benchWithGPA);
91+
try suite.addWithAllocator("HashMap (GPA)", benchHashMapOperations);
92+
93+
const stdout = std.fs.File.stdout();
94+
var buf: [256]u8 = undefined;
95+
const msg = try std.fmt.bufPrint(&buf, "\n{s}[GeneralPurposeAllocator]{s}\n", .{ bench.Formatter.CYAN, bench.Formatter.RESET });
96+
try stdout.writeAll(msg);
97+
98+
try suite.run();
99+
}
100+
101+
// Suite with Arena
102+
{
103+
var suite = bench.BenchmarkSuite.init(arena_allocator);
104+
defer suite.deinit();
105+
106+
try suite.addWithAllocator("ArrayList (Arena)", benchWithArena);
107+
try suite.addWithAllocator("HashMap (Arena)", benchHashMapOperations);
108+
109+
const stdout = std.fs.File.stdout();
110+
var buf: [256]u8 = undefined;
111+
const msg = try std.fmt.bufPrint(&buf, "\n{s}[ArenaAllocator]{s}\n", .{ bench.Formatter.CYAN, bench.Formatter.RESET });
112+
try stdout.writeAll(msg);
113+
114+
try suite.run();
115+
}
116+
}

0 commit comments

Comments
 (0)