Skip to content

Commit 6c45e71

Browse files
WiseMrMusav0-e
andauthored
ci: add continuous benchmark report (#43)
Closes #39 --------- Co-authored-by: v0-e <xyz.vieira@gmail.com>
1 parent 79a46a7 commit 6c45e71

4 files changed

Lines changed: 167 additions & 1 deletion

File tree

.github/workflows/benchmark.yml

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# TODO(template) this workflow requires a `gh-pages` branch to exist.
2+
# Create it once with:
3+
# git checkout --orphan gh-pages
4+
# git reset --hard
5+
# git commit --allow-empty -m "init gh-pages"
6+
# git push origin gh-pages
7+
#
8+
# The benchmark dashboard will be available at:
9+
# https://<org>.github.io/<repo>/dev/bench/
10+
name: Benchmarks
11+
12+
on:
13+
push:
14+
branches: ["main"]
15+
pull_request:
16+
branches: ["main"]
17+
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.ref }}
20+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
21+
22+
permissions:
23+
contents: write
24+
deployments: write
25+
pull-requests: write
26+
27+
env:
28+
CARGO_TERM_COLOR: always
29+
CARGO_INCREMENTAL: 0
30+
CARGO_NET_RETRY: 10
31+
RUSTUP_MAX_RETRIES: 10
32+
33+
jobs:
34+
benchmark:
35+
name: Continuous benchmarking
36+
runs-on: ubuntu-latest
37+
timeout-minutes: 30
38+
steps:
39+
- uses: actions/checkout@v4
40+
41+
- name: Install Rust toolchain
42+
uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # stable
43+
id: rust-toolchain
44+
with:
45+
toolchain: stable
46+
47+
- uses: actions/cache@v4
48+
with:
49+
path: |
50+
~/.cargo/bin/
51+
~/.cargo/registry/index/
52+
~/.cargo/registry/cache/
53+
~/.cargo/git/db/
54+
target/
55+
key: ${{ runner.os }}-bench-${{ steps.rust-toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
56+
restore-keys: |
57+
${{ runner.os }}-bench-${{ steps.rust-toolchain.outputs.cachekey }}-
58+
${{ runner.os }}-bench-
59+
60+
# TODO(template) update the bench command if you use a different
61+
# benchmark harness or need to pass extra flags
62+
- name: Run benchmarks
63+
shell: bash
64+
run: |
65+
set -euo pipefail
66+
cargo bench -p template_crate --bench benchmark -- --output-format bencher 2>/dev/null | tee benchmark-output.txt
67+
68+
# On PRs: restore the most-recent baseline written by a main-branch run.
69+
# Using only restore-keys (no matching primary key) guarantees we always
70+
# get the latest entry; the primary key includes the run ID so each main
71+
# run saves a fresh entry and PRs never hit a stale one.
72+
# Note: if no baseline cache exists yet (e.g. the very first PR before any
73+
# main-branch run has completed), the restore will miss and no regression
74+
# alert will fire. This is expected and benign — the action creates a fresh
75+
# data file and the next main-branch run will establish the baseline.
76+
- name: Restore benchmark baseline
77+
if: github.event_name == 'pull_request'
78+
uses: actions/cache/restore@v4
79+
with:
80+
path: ./cache
81+
key: ${{ runner.os }}-benchmark-baseline-${{ github.run_id }}
82+
restore-keys: |
83+
${{ runner.os }}-benchmark-baseline-
84+
85+
- name: Store benchmark result (PR)
86+
if: github.event_name == 'pull_request'
87+
uses: benchmark-action/github-action-benchmark@4bdcce38c94cec68da58d012ac24b7b1155efe8b # v1
88+
with:
89+
# TODO(template) update the name to match your project
90+
name: Rust Template Benchmark
91+
tool: "cargo"
92+
output-file-path: benchmark-output.txt
93+
external-data-json-path: ./cache/benchmark-data.json
94+
alert-threshold: "130%"
95+
comment-on-alert: true
96+
fail-on-alert: true
97+
github-token: ${{ secrets.GITHUB_TOKEN }}
98+
99+
# On main: push results to gh-pages for the historical dashboard, then
100+
# save the updated baseline so future PRs compare against current main.
101+
# external-data-json-path writes the latest result into ./cache so the
102+
# subsequent save step has data to cache for PR comparisons.
103+
- name: Store benchmark result (main)
104+
if: github.event_name == 'push'
105+
uses: benchmark-action/github-action-benchmark@4bdcce38c94cec68da58d012ac24b7b1155efe8b # v1
106+
with:
107+
# TODO(template) update the name to match your project
108+
name: Rust Template Benchmark
109+
tool: "cargo"
110+
output-file-path: benchmark-output.txt
111+
external-data-json-path: ./cache/benchmark-data.json
112+
gh-pages-branch: gh-pages
113+
benchmark-data-dir-path: dev/bench
114+
alert-threshold: "130%"
115+
comment-on-alert: true
116+
github-token: ${{ secrets.GITHUB_TOKEN }}
117+
auto-push: true
118+
119+
# Save the freshly-updated benchmark data as the new baseline.
120+
# The key embeds the run ID so every main run creates a new cache entry;
121+
# actions/cache would skip saving if the key already existed.
122+
- name: Save benchmark baseline
123+
if: github.event_name == 'push'
124+
uses: actions/cache/save@v4
125+
with:
126+
path: ./cache
127+
key: ${{ runner.os }}-benchmark-baseline-${{ github.run_id }}

.github/workflows/build-and-test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,7 @@ jobs:
3838
- uses: Swatinem/rust-cache@v2
3939
- name: Build
4040
run: cargo test --workspace --verbose --no-run
41+
- name: Build all targets
42+
run: cargo build --workspace --all-features --all-targets
4143
- name: Run tests
42-
run: cargo test --workspace --verbose
44+
run: cargo test --workspace --verbose

template_crate/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@ license.workspace = true
1515
thiserror = { version = "1.0", default-features = false }
1616

1717
[dev-dependencies]
18+
criterion = { version = "0.5", features = ["html_reports"] }
1819
proptest = { workspace = true }
1920

2021
# TODO(template)
2122
# don't forget to put this at every crate
2223
# to inherit workspace's lints
24+
[[bench]]
25+
name = "benchmark"
26+
harness = false
27+
2328
[lints]
2429
workspace = true
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//! Benchmarks for template_crate
2+
3+
use criterion::{Criterion, black_box, criterion_group};
4+
use template_crate::{add_small_integers, sub_small_integers};
5+
6+
/// Benchmarks for `add_small_integers` function
7+
fn bench_add_small_integers(c: &mut Criterion) {
8+
c.bench_function("add_small_integers valid", |b| {
9+
b.iter(|| add_small_integers(black_box(50), black_box(30)))
10+
});
11+
12+
c.bench_function("add_small_integers bound check", |b| {
13+
b.iter(|| add_small_integers(black_box(200), black_box(5)))
14+
});
15+
}
16+
17+
/// Benchmarks for `sub_small_integers` function
18+
fn bench_sub_small_integers(c: &mut Criterion) {
19+
c.bench_function("sub_small_integers valid", |b| {
20+
b.iter(|| sub_small_integers(black_box(50), black_box(30)))
21+
});
22+
23+
c.bench_function("sub_small_integers bound check", |b| {
24+
b.iter(|| sub_small_integers(black_box(200), black_box(5)))
25+
});
26+
}
27+
28+
/// Entry point for benchmarks
29+
fn main() {
30+
criterion_group!(benches, bench_add_small_integers, bench_sub_small_integers);
31+
benches();
32+
}

0 commit comments

Comments
 (0)