-
Notifications
You must be signed in to change notification settings - Fork 93
feat(bench): add Criterion.rs benchmark scaffold (mohu-benchmarks) #248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7a3c5ac
9d2b2e9
89c95c3
4219497
2544e58
d1f9012
9d5a58f
73c4483
a9acc32
f14e789
dd94e4a
c7c1edc
d7c2914
ed6ce00
04006f2
ebdb5d4
0048bbd
4f24443
d4f975f
a9171cf
bcb2617
e51f953
07b2a42
951ae66
dc84f4a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| name: Benchmark | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| schedule: | ||
| # Run every Monday at 3:00 UTC | ||
| - cron: '0 3 * * 1' | ||
|
|
||
| env: | ||
| CARGO_TERM_COLOR: always | ||
| RUST_BACKTRACE: 1 | ||
|
|
||
| jobs: | ||
| benchmark: | ||
| name: Run Benchmarks | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dtolnay/rust-toolchain@stable | ||
| - uses: Swatinem/rust-cache@v2 | ||
| - name: Run benchmarks | ||
| run: | | ||
| cd crates/mohu-benchmarks | ||
| cargo bench -- --output-format bencher | tee output.txt | ||
| - name: Upload benchmark results | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: benchmark-results | ||
| path: crates/mohu-benchmarks/output.txt | ||
| retention-days: 30 | ||
| - name: Upload Criterion reports | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: criterion-reports | ||
| path: crates/mohu-benchmarks/target/criterion/ | ||
| retention-days: 30 | ||
| # Optional: Enable github-action-benchmark for trend charts | ||
| # To enable: | ||
| # 1. Uncomment the step below | ||
| # 2. Create a GitHub secret named BENCHMARK_TOKEN (or use GITHUB_TOKEN) | ||
| # 3. Set up the benchmark-data repository or use the default | ||
| # See: https://github.com/benchmark-action/github-action-benchmark | ||
| # - name: Store benchmark result | ||
| # uses: benchmark-action/github-action-benchmark@v1 | ||
| # with: | ||
| # tool: 'cargo' | ||
| # output-file-path: crates/mohu-benchmarks/output.txt | ||
| # github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| # auto-push: true | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,7 @@ jobs: | |
| runs-on: ubuntu-latest | ||
| if: github.event_name == 'pull_request' | ||
| steps: | ||
| - uses: christophebedard/dco-check@v0.5.0 | ||
| - uses: christophebedard/dco-check@0.5.1 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pin the GitHub Action to a full commit SHA, not a tag. Using Suggested change- - uses: christophebedard/dco-check@0.5.1
+ - uses: christophebedard/dco-check@<full_commit_sha>🧰 Tools🪛 zizmor (1.25.2)[error] 26-26: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI Agents |
||
| with: | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| [package] | ||
| name = "mohu-benchmarks" | ||
| version = "0.1.0" | ||
| edition = "2024" | ||
|
|
||
| [dependencies] | ||
| criterion = { version = "0.4", features = ["html_reports"] } | ||
| # Use the workspace mohu-array crate when available; maintainers can enable this | ||
| # once the public API for benchmarks is agreed. | ||
| mohu-array = { workspace = true } | ||
|
Comment on lines
+6
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify whether criterion is centralized in root workspace deps
rg -n --glob 'Cargo.toml' '^\[workspace\.dependencies\]|^criterion\s*=' -C2Repository: mohu-org/mohu Length of output: 747 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Show root workspace dependency block lines around where criterion would be declared
root_cargo="Cargo.toml"
echo "== Root Cargo.toml: workspace.dependencies (lines 40-120) =="
nl -ba "$root_cargo" | sed -n '40,120p'
echo "== Search root Cargo.toml for criterion declaration =="
rg -n '^\s*criterion\s*=' "$root_cargo" || true
echo "== Search entire repo for criterion entries in [workspace.dependencies] =="
rg -n --glob 'Cargo.toml' --context 2 '^\[workspace\.dependencies\]|\bcriterion\s*=\s*' "$root_cargo" crates || trueRepository: mohu-org/mohu Length of output: 179 🏁 Script executed: #!/bin/bash
set -euo pipefail
root_cargo="Cargo.toml"
echo "== Find [workspace.dependencies] range in root Cargo.toml =="
grep -n '^\[workspace\.dependencies\]' -n "$root_cargo" || true
echo "== Search root Cargo.toml for criterion declarations =="
rg -n '^\s*criterion\s*=' "$root_cargo" || true
echo "== Print workspace.dependencies block (approx. lines 35-110) =="
sed -n '35,110p' "$root_cargo"Repository: mohu-org/mohu Length of output: 3748 🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n --glob 'Cargo.toml' 'criterion\s*=\s*\{' .
rg -n --glob 'Cargo.toml' '^\s*criterion\s*=' .
rg -n --glob 'Cargo.toml' '\[workspace\.dependencies\]' Cargo.tomlRepository: mohu-org/mohu Length of output: 283 Use workspace-managed dependency for
[dependencies]
criterion = { version = "0.4", features = ["html_reports"] }This conflicts with the workspace rule (“all external dependency versions must live in root 🤖 Prompt for AI Agents |
||
|
|
||
| [package.metadata] | ||
| description = "Benchmark suite scaffolding for the Mohu project using Criterion.rs" | ||
| repository = "https://github.com/mohu-org/mohu" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # Mohu Benchmarks | ||
|
|
||
| This crate provides a Criterion.rs-based benchmark scaffold for the Mohu project. It intentionally starts small with well-documented microbenchmarks for: | ||
|
|
||
| - Element-wise arithmetic (vector add) | ||
| - Reduction (sum) | ||
| - Memory stride access comparison (row-major vs column-major scanning) | ||
|
|
||
| ## Architecture Note | ||
|
|
||
| **Important**: The ROADMAP.md suggests `mohu-benchmarks` should be a standalone repository to allow anyone to run benchmarks without building the full library. However, this PR implements it as a workspace member crate for tighter integration with the CI pipeline and easier maintenance. If maintainers prefer the standalone repo approach, this can be migrated in a follow-up PR. | ||
|
|
||
| ## Current Status | ||
|
|
||
| **Note**: `mohu-array` is currently in stub status (module files are empty as documented in CRATE_MAP.md). The current benchmarks use plain `Vec<T>` operations as placeholders. Once `mohu-array` is implemented, these benchmarks should be extended to use the actual array API. | ||
|
|
||
| ### What's Implemented | ||
|
|
||
| - Basic microbenchmarks using `Vec<T>` operations | ||
| - Integration test placeholder in `tests/` directory | ||
| - CI workflow for scheduled benchmark runs (`.github/workflows/benchmark.yml`) | ||
| - Proper use of `criterion::black_box()` to prevent compiler optimization | ||
|
|
||
| ### Next Steps | ||
|
|
||
| Once `mohu-array` is implemented, maintainers and contributors should extend this suite with: | ||
|
|
||
| 1. **Integration Tests**: Replace the placeholder in `tests/integration_test.rs` with actual `mohu-array` construction and operation tests | ||
| 2. **Array Benchmarks**: Extend benchmarks to use `mohu-array` compute paths (ufunc/reduction APIs directly in bench closures) | ||
| 3. **I/O Benchmarks**: Add benchmarks for `.npy`/`.csv` using `mohu-io` | ||
| 4. **Cross-comparisons**: Add NumPy comparisons (scripted externally via Python) | ||
| 5. **Advanced Experiments**: SIMD vs scalar kernels and threaded vs sequential experiments | ||
| 6. **Baseline Reports**: Generate and commit baseline `target/criterion/` HTML reports or JSON summaries for regression detection (requires properly configured build environment with MSVC toolchain on Windows) | ||
|
|
||
| ## Running Benchmarks | ||
|
|
||
| Run locally: | ||
|
|
||
| ```sh | ||
| cd crates/mohu-benchmarks | ||
| cargo bench --bench bench_core | ||
| ``` | ||
|
|
||
| Run with bencher output format (for CI): | ||
|
|
||
| ```sh | ||
| cd crates/mohu-benchmarks | ||
| cargo bench -- --output-format bencher | tee output.txt | ||
| ``` | ||
|
|
||
| ## CI Integration | ||
|
|
||
| A scheduled benchmark workflow is configured in `.github/workflows/benchmark.yml`: | ||
| - Runs every Monday at 3:00 UTC via cron schedule | ||
| - Can also be triggered manually via `workflow_dispatch` | ||
| - Uploads benchmark results and Criterion reports as artifacts (30-day retention) | ||
| - Uses `bencher` output format for potential integration with `github-action-benchmark` for trend charts | ||
|
|
||
| For full regression detection, consider: | ||
| - Storing Criterion reports in S3-compatible storage | ||
| - Using `github-action-benchmark` for trend visualization | ||
| - Comparing specific baseline outputs across runs |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| use criterion::{black_box, criterion_group, criterion_main, Criterion}; | ||
|
|
||
| // Lightweight core benchmarks scaffold. These are intentionally simple and | ||
| // provide maintainers a starting point to add mohu-array-specific benchmarks. | ||
|
|
||
| fn bench_arithmetic_add(c: &mut Criterion) { | ||
| let size = 1_000_000usize; | ||
| let a: Vec<f64> = (0..size).map(|i| (i as f64) * 0.5).collect(); | ||
| let b: Vec<f64> = (0..size).map(|i| (i as f64) * 1.5).collect(); | ||
|
|
||
| c.bench_function("vec_add_iter", |bencher| { | ||
| bencher.iter(|| { | ||
| let mut r = vec![0.0f64; size]; | ||
| for i in 0..size { | ||
| r[i] = black_box(a[i]) + black_box(b[i]); | ||
| } | ||
| black_box(r) | ||
| }) | ||
| }); | ||
| } | ||
|
|
||
| fn bench_reduction_sum(c: &mut Criterion) { | ||
| let size = 2_000_000usize; | ||
| let a: Vec<f64> = (0..size).map(|i| (i as f64) * 0.25).collect(); | ||
|
|
||
| c.bench_function("vec_sum_iter", |bencher| { | ||
| bencher.iter(|| { | ||
| let mut s = 0.0f64; | ||
| for &v in &a { | ||
| s += black_box(v); | ||
| } | ||
| black_box(s) | ||
| }) | ||
| }); | ||
| } | ||
|
|
||
| fn bench_stride_access(c: &mut Criterion) { | ||
| let rows = 10_000usize; | ||
| let cols = 1_000usize; | ||
| // simulate flat storage | ||
| let mut data: Vec<f64> = vec![0.0; rows * cols]; | ||
| for i in 0..(rows * cols) { data[i] = (i as f64) % 100.0; } | ||
|
|
||
| c.bench_function("row_major_sum", |bencher| { | ||
| bencher.iter(|| { | ||
| let mut s = 0.0f64; | ||
| for r in 0..rows { | ||
| for cidx in 0..cols { | ||
| s += black_box(data[r * cols + cidx]); | ||
| } | ||
| } | ||
| black_box(s) | ||
| }) | ||
| }); | ||
|
|
||
| c.bench_function("col_major_sum", |bencher| { | ||
| bencher.iter(|| { | ||
| let mut s = 0.0f64; | ||
| for cidx in 0..cols { | ||
| for r in 0..rows { | ||
| s += black_box(data[r * cols + cidx]); | ||
| } | ||
| } | ||
| black_box(s) | ||
| }) | ||
| }); | ||
| } | ||
|
|
||
| criterion_group!(benches, bench_arithmetic_add, bench_reduction_sum, bench_stride_access); | ||
| criterion_main!(benches); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // Integration test for mohu-array usage | ||
| // | ||
| // This test is a placeholder that will be expanded once mohu-array is implemented. | ||
| // Currently, mohu-array modules are stubs (empty files) as documented in CRATE_MAP.md. | ||
| // | ||
| // When mohu-array is implemented, this test should: | ||
| // - Construct a mohu-array object (e.g., NdArray<T>) | ||
| // - Perform a simple operation (e.g., element-wise add, reduction sum) | ||
| // - Assert a known result to verify the wiring works | ||
| // | ||
| // Example (to be implemented): | ||
| // ```rust | ||
| // use mohu_array::array::NdArray; | ||
| // | ||
| // #[test] | ||
| // fn test_array_construction_and_sum() { | ||
| // let arr = NdArray::from_vec(vec![1.0, 2.0, 3.0, 4.0]); | ||
| // let sum = arr.sum(); | ||
| // assert!((sum - 10.0).abs() < 1e-9); | ||
| // } | ||
| // ``` | ||
|
|
||
| #[test] | ||
| fn test_placeholder() { | ||
| // Placeholder test to ensure the tests directory is recognized | ||
| // This will be replaced with actual mohu-array integration tests | ||
| assert!(true); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.