Skip to content
Merged
113 changes: 113 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# TODO(template) this workflow requires a `gh-pages` branch to exist.
# Create it once with:
# git checkout --orphan gh-pages
# git reset --hard
# git commit --allow-empty -m "init gh-pages"
# git push origin gh-pages
#
# The benchmark dashboard will be available at:
# https://<org>.github.io/<repo>/dev/bench/
name: Benchmarks

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: write
deployments: write
pull-requests: write

env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTUP_MAX_RETRIES: 10

jobs:
benchmark:
name: Continuous benchmarking
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-bench-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-bench-

# TODO(template) update the bench command if you use a different
# benchmark harness or need to pass extra flags
- name: Run benchmarks
shell: bash
run: |
set -euo pipefail
cargo bench -p template_crate --bench benchmark -- --output-format bencher 2>&1 | tee benchmark-output.txt

# On PRs: restore the most-recent baseline written by a main-branch run.
# Using only restore-keys (no matching primary key) guarantees we always
# get the latest entry; the primary key includes the run ID so each main
# run saves a fresh entry and PRs never hit a stale one.
- name: Restore benchmark baseline
if: github.event_name == 'pull_request'
uses: actions/cache/restore@v4
with:
path: ./cache
key: ${{ runner.os }}-benchmark-baseline-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-benchmark-baseline-

- name: Store benchmark result (PR)
if: github.event_name == 'pull_request'
uses: benchmark-action/github-action-benchmark@v1
with:
# TODO(template) update the name to match your project
name: Benchmark
tool: "cargo"
output-file-path: benchmark-output.txt
external-data-json-path: ./cache/benchmark-data.json
alert-threshold: "130%"
comment-on-alert: true
fail-on-alert: true
github-token: ${{ secrets.GITHUB_TOKEN }}

# On main: push results to gh-pages for the historical dashboard, then
# save the updated baseline so future PRs compare against current main.
- name: Store benchmark result (main)
if: github.event_name == 'push'
uses: benchmark-action/github-action-benchmark@v1
with:
# TODO(template) update the name to match your project
name: Rust Template Benchmark
tool: "cargo"
output-file-path: benchmark-output.txt
gh-pages-branch: gh-pages
benchmark-data-dir-path: dev/bench
alert-threshold: "130%"
comment-on-alert: true
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true

# Save the freshly-updated benchmark data as the new baseline.
# The key embeds the run ID so every main run creates a new cache entry;
# actions/cache would skip saving if the key already existed.
- name: Save benchmark baseline
if: github.event_name == 'push'
uses: actions/cache/save@v4
with:
path: ./cache
key: ${{ runner.os }}-benchmark-baseline-${{ github.run_id }}
4 changes: 3 additions & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,7 @@ jobs:
- uses: Swatinem/rust-cache@v2
- name: Build
run: cargo test --workspace --verbose --no-run
- name: Build all targets
run: cargo build --workspace --all-features --all-targets
- name: Run tests
run: cargo test --workspace --verbose
run: cargo test --workspace --verbose
5 changes: 5 additions & 0 deletions template_crate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ license.workspace = true
thiserror = { version = "1.0", default-features = false }

[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }
proptest = { workspace = true }

# TODO(template)
# don't forget to put this at every crate
# to inherit workspace's lints
[[bench]]
name = "benchmark"
harness = false

[lints]
workspace = true
32 changes: 32 additions & 0 deletions template_crate/benches/benchmark.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! Benchmarks for template_crate

use criterion::{Criterion, black_box, criterion_group};
use template_crate::{add_small_integers, sub_small_integers};

/// Benchmarks for `add_small_integers` function
fn bench_add_small_integers(c: &mut Criterion) {
c.bench_function("add_small_integers valid", |b| {
b.iter(|| add_small_integers(black_box(50), black_box(30)))
});

c.bench_function("add_small_integers bound check", |b| {
b.iter(|| add_small_integers(black_box(200), black_box(5)))
});
}

/// Benchmarks for `sub_small_integers` function
fn bench_sub_small_integers(c: &mut Criterion) {
c.bench_function("sub_small_integers valid", |b| {
b.iter(|| sub_small_integers(black_box(50), black_box(30)))
});

c.bench_function("sub_small_integers bound check", |b| {
b.iter(|| sub_small_integers(black_box(200), black_box(5)))
});
}

/// Entry point for benchmarks
fn main() {
criterion_group!(benches, bench_add_small_integers, bench_sub_small_integers);
benches();
}
Loading