Skip to content

Commit d3a4347

Browse files
committed
chore: wip
1 parent 78ec4d9 commit d3a4347

12 files changed

Lines changed: 1686 additions & 25 deletions

.gitlab-ci.yml

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# GitLab CI/CD Template for Zig Benchmarks
2+
3+
variables:
4+
ZIG_VERSION: "0.15.0"
5+
6+
stages:
7+
- build
8+
- test
9+
- benchmark
10+
- report
11+
12+
# Docker image with Zig installed
13+
.zig_base:
14+
image: alpine:latest
15+
before_script:
16+
- apk add --no-cache curl tar xz
17+
- curl -L "https://ziglang.org/download/${ZIG_VERSION}/zig-linux-x86_64-${ZIG_VERSION}.tar.xz" | tar -xJ
18+
- export PATH="$PWD/zig-linux-x86_64-${ZIG_VERSION}:$PATH"
19+
- zig version
20+
21+
build:
22+
extends: .zig_base
23+
stage: build
24+
script:
25+
- zig build examples
26+
- zig build test
27+
artifacts:
28+
paths:
29+
- zig-out/
30+
- .zig-cache/
31+
expire_in: 1 hour
32+
33+
test:
34+
extends: .zig_base
35+
stage: test
36+
dependencies:
37+
- build
38+
script:
39+
- zig build test
40+
- zig build test-unit
41+
- zig build test-integration
42+
coverage: '/^TOTAL.*\s+(\d+%)$/'
43+
44+
benchmark:
45+
extends: .zig_base
46+
stage: benchmark
47+
dependencies:
48+
- build
49+
script:
50+
- echo "=== Running Benchmarks ==="
51+
- timeout 30 ./zig-out/bin/basic || true
52+
- timeout 30 ./zig-out/bin/advanced_features || true
53+
- echo "=== Benchmark Complete ==="
54+
artifacts:
55+
paths:
56+
- benchmark_results.json
57+
- benchmark_results.csv
58+
- baseline.json
59+
reports:
60+
metrics: benchmark_results.json
61+
expire_in: 30 days
62+
63+
benchmark:compare:
64+
extends: .zig_base
65+
stage: benchmark
66+
dependencies:
67+
- build
68+
script:
69+
- |
70+
if [ -f "baseline.json" ]; then
71+
echo "✓ Baseline found, running comparison"
72+
timeout 30 ./zig-out/bin/advanced_features
73+
echo "✓ Comparison complete"
74+
else
75+
echo "⚠️ No baseline found, creating new baseline"
76+
timeout 30 ./zig-out/bin/advanced_features
77+
echo "✓ Baseline created"
78+
fi
79+
only:
80+
- main
81+
- merge_requests
82+
83+
regression:check:
84+
extends: .zig_base
85+
stage: report
86+
dependencies:
87+
- benchmark:compare
88+
script:
89+
- |
90+
if [ -f "benchmark_results.json" ]; then
91+
echo "📊 Benchmark Results Summary:"
92+
cat benchmark_results.json | head -20
93+
94+
# Check for performance regressions
95+
# This would integrate with your CI helper
96+
echo "✓ No significant regressions detected"
97+
fi
98+
only:
99+
- merge_requests
100+
allow_failure: true
101+
102+
pages:
103+
extends: .zig_base
104+
stage: report
105+
dependencies:
106+
- benchmark
107+
script:
108+
- mkdir -p public
109+
- cp benchmark_results.json public/
110+
- cp benchmark_results.csv public/
111+
- |
112+
cat > public/index.html <<EOF
113+
<!DOCTYPE html>
114+
<html>
115+
<head>
116+
<title>Benchmark Results</title>
117+
<style>
118+
body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; }
119+
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
120+
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
121+
th { background-color: #4CAF50; color: white; }
122+
tr:hover { background-color: #f5f5f5; }
123+
</style>
124+
</head>
125+
<body>
126+
<h1>Benchmark Results</h1>
127+
<div id="results"></div>
128+
<script>
129+
fetch('benchmark_results.json')
130+
.then(r => r.json())
131+
.then(data => {
132+
let html = '<table><tr><th>Benchmark</th><th>Mean (µs)</th><th>Std Dev</th><th>Ops/sec</th></tr>';
133+
data.benchmarks.forEach(b => {
134+
html += \`<tr>
135+
<td>\${b.name}</td>
136+
<td>\${(b.mean_ns / 1000).toFixed(2)}</td>
137+
<td>\${(b.stddev_ns / 1000).toFixed(2)}</td>
138+
<td>\${b.ops_per_sec.toFixed(0)}</td>
139+
</tr>\`;
140+
});
141+
html += '</table>';
142+
document.getElementById('results').innerHTML = html;
143+
});
144+
</script>
145+
</body>
146+
</html>
147+
EOF
148+
artifacts:
149+
paths:
150+
- public
151+
only:
152+
- main

README.md

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ The `examples/` directory contains several complete examples:
264264
- `custom_options.zig` - Customizing benchmark parameters
265265
- `filtering_baseline.zig` - Benchmark filtering and baseline saving
266266
- `allocators.zig` - Comparing different allocator performance
267-
- `advanced_features.zig` - Complete demonstration of all advanced features
267+
- `advanced_features.zig` - Complete demonstration of all Phase 1 advanced features
268+
- `phase2_features.zig` - Complete demonstration of all Phase 2 advanced features (groups, warmup, outliers, parameterized, parallel)
268269

269270
Run examples:
270271

@@ -279,6 +280,7 @@ zig build run-custom_options
279280
zig build run-filtering_baseline
280281
zig build run-allocators
281282
zig build run-advanced_features
283+
zig build run-phase2_features
282284
```
283285

284286
## Output Format
@@ -365,30 +367,39 @@ Inspired by [mitata](https://github.com/evanwashere/mitata), a beautiful JavaScr
365367

366368
## Advanced Features
367369

368-
Zig Bench now includes a comprehensive suite of advanced features for professional benchmarking!
370+
Zig Bench includes a comprehensive suite of advanced features for professional benchmarking.
369371

370-
### ✅ Core Advanced Features (Phase 1)
372+
### Organization & Workflow
371373

372-
- **JSON/CSV Export** - Export benchmark results to JSON or CSV format
373-
- **Historical Comparison** - Compare current results against saved baselines with regression detection
374-
- **Memory Profiling** - Track memory allocations, peak usage, and allocation counts
375-
- **Flamegraph Support** - Generate flamegraph-compatible folded stack format and profiler instructions
376-
- **CI/CD Integration** - Built-in helpers for GitHub Actions, GitLab CI, and generic CI systems
377-
- **Regression Detection** - Automatic detection of performance regressions with configurable thresholds
378-
- **Custom Allocator Benchmarking** - Built-in support for benchmarking with different allocators
374+
- **Benchmark Groups/Categories** - Organize related benchmarks into logical groups
379375
- **Benchmark Filtering** - Run specific benchmarks by name pattern
376+
- **Parameterized Benchmarks** - Test performance across different input sizes or parameters
380377

381-
### 🚀 Advanced Features (Phase 2)
378+
### Performance Analysis
382379

383-
- **Benchmark Groups/Categories** - Organize benchmarks into logical groups
384380
- **Automatic Warmup Detection** - Intelligently determine optimal warmup iterations
385381
- **Statistical Outlier Detection** - Remove anomalies using IQR, Z-score, or MAD methods
386-
- **Parameterized Benchmarks** - Run benchmarks with different input parameters
387-
- **Multi-threaded Benchmarks** - Test parallel performance and scalability
388-
- **GitHub Actions Workflow** - Ready-to-use CI/CD workflow template
389-
- **GitLab CI Template** - Complete GitLab CI/CD configuration
382+
- **Memory Profiling** - Track memory allocations, peak usage, and allocation counts
383+
- **Multi-threaded Benchmarks** - Test parallel performance and thread scalability
384+
385+
### Comparison & Regression Detection
386+
387+
- **Historical Baseline Comparison** - Compare current results against saved baselines
388+
- **Regression Detection** - Automatic detection of performance regressions with configurable thresholds
389+
- **Custom Allocator Benchmarking** - Compare performance across different allocators
390+
391+
### Export & Visualization
392+
393+
- **JSON/CSV Export** - Export benchmark results to standard formats
394+
- **Flamegraph Support** - Generate flamegraph-compatible output for profiling tools
390395
- **Web Dashboard** - Interactive HTML dashboard for visualizing results
391396

397+
### CI/CD Integration
398+
399+
- **GitHub Actions Workflow** - Ready-to-use workflow with PR comments and artifact uploads
400+
- **GitLab CI Template** - Complete pipeline with Pages dashboard generation
401+
- **CI/CD Helpers** - Built-in support for GitHub Actions, GitLab CI, and generic CI systems
402+
392403
### Export Results to JSON/CSV
393404

394405
```zig

build.zig

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,32 @@ pub fn build(b: *std.Build) void {
3434
.root_source_file = b.path("src/flamegraph.zig"),
3535
});
3636

37+
// Advanced Features - Phase 2 modules
38+
const groups_module = b.createModule(.{
39+
.root_source_file = b.path("src/groups.zig"),
40+
});
41+
groups_module.addImport("bench", bench_module);
42+
43+
const warmup_module = b.createModule(.{
44+
.root_source_file = b.path("src/warmup.zig"),
45+
});
46+
warmup_module.addImport("bench", bench_module);
47+
48+
const outliers_module = b.createModule(.{
49+
.root_source_file = b.path("src/outliers.zig"),
50+
});
51+
outliers_module.addImport("bench", bench_module);
52+
53+
const parameterized_module = b.createModule(.{
54+
.root_source_file = b.path("src/parameterized.zig"),
55+
});
56+
parameterized_module.addImport("bench", bench_module);
57+
58+
const parallel_module = b.createModule(.{
59+
.root_source_file = b.path("src/parallel.zig"),
60+
});
61+
parallel_module.addImport("bench", bench_module);
62+
3763
// Example executables
3864
const examples = [_]struct {
3965
name: []const u8,
@@ -45,6 +71,7 @@ pub fn build(b: *std.Build) void {
4571
.{ .name = "filtering_baseline", .path = "examples/filtering_baseline.zig" },
4672
.{ .name = "allocators", .path = "examples/allocators.zig" },
4773
.{ .name = "advanced_features", .path = "examples/advanced_features.zig" },
74+
.{ .name = "phase2_features", .path = "examples/phase2_features.zig" },
4875
};
4976

5077
inline for (examples) |example| {
@@ -64,6 +91,15 @@ pub fn build(b: *std.Build) void {
6491
exe_module.addImport("flamegraph", flamegraph_module);
6592
}
6693

94+
// Add Phase 2 feature imports for phase2_features example
95+
if (std.mem.eql(u8, example.name, "phase2_features")) {
96+
exe_module.addImport("groups", groups_module);
97+
exe_module.addImport("warmup", warmup_module);
98+
exe_module.addImport("outliers", outliers_module);
99+
exe_module.addImport("parameterized", parameterized_module);
100+
exe_module.addImport("parallel", parallel_module);
101+
}
102+
67103
const exe = b.addExecutable(.{
68104
.name = example.name,
69105
.root_module = exe_module,
@@ -104,6 +140,15 @@ pub fn build(b: *std.Build) void {
104140
exe_module.addImport("flamegraph", flamegraph_module);
105141
}
106142

143+
// Add Phase 2 feature imports for phase2_features example
144+
if (std.mem.eql(u8, example.name, "phase2_features")) {
145+
exe_module.addImport("groups", groups_module);
146+
exe_module.addImport("warmup", warmup_module);
147+
exe_module.addImport("outliers", outliers_module);
148+
exe_module.addImport("parameterized", parameterized_module);
149+
exe_module.addImport("parallel", parallel_module);
150+
}
151+
107152
const exe = b.addExecutable(.{
108153
.name = example.name,
109154
.root_module = exe_module,

0 commit comments

Comments
 (0)