name: Nightly Benchmarks
on:
schedule:
- cron: '0 2 * * *' workflow_dispatch:
permissions:
contents: read
issues: write
jobs:
compile:
name: bench / compile
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-bench-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-bench-
- name: Cache bench target
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-bench-target-${{ hashFiles('**/Cargo.lock', 'benches/**', 'src/**/*.rs') }}
- name: Compile benchmarks
run: cargo bench --no-run
benchmark:
name: bench / ${{ matrix.name }}
runs-on: ubuntu-latest
needs: [compile]
timeout-minutes: 360
strategy:
fail-fast: false matrix:
include:
- name: insert
filter: "^insert/"
file: bench_insert.txt
threshold: "0.99"
- name: insert_file
filter: "^insert_file/"
file: bench_insert_file.txt
threshold: "0.99"
- name: query
filter: "^query/"
file: bench_query.txt
threshold: "0.99"
- name: time_travel
filter: "^time_travel/"
file: bench_time_travel.txt
threshold: "0.99"
- name: recursion
filter: "^recursion/"
file: bench_recursion.txt
threshold: "0.99"
- name: open
filter: "^open/"
file: bench_open.txt
threshold: "0.99"
- name: checkpoint
filter: "^checkpoint"
file: bench_checkpoint.txt
threshold: "0.99"
- name: concurrent/readers
filter: "^concurrent/readers/"
file: bench_concurrent_readers.txt
threshold: "0.999"
- name: concurrent/readers_plus_writer
filter: "^concurrent/readers_plus_writer/"
file: bench_concurrent_mixed.txt
threshold: "0.999"
- name: concurrent/serialized_writers
filter: "^concurrent/serialized_writers/"
file: bench_concurrent_writers.txt
threshold: "0.999"
- name: concurrent_file/readers
filter: "^concurrent_file/readers/"
file: bench_concurrent_file_readers.txt
threshold: "0.999"
- name: concurrent_file/readers_plus_writer
filter: "^concurrent_file/readers_plus_writer/"
file: bench_concurrent_file_mixed.txt
threshold: "0.999"
- name: concurrent_file/serialized_writers
filter: "^concurrent_file/serialized_writers/"
file: bench_concurrent_file_writers.txt
threshold: "0.999"
- name: concurrent_btree_scan
filter: "^concurrent_btree_scan"
file: bench_concurrent_btree_scan.txt
threshold: "0.999"
- name: negation
filter: "^negation/"
file: bench_negation.txt
threshold: "0.99"
- name: disjunction
filter: "^disjunction/"
file: bench_disjunction.txt
threshold: "0.99"
- name: aggregation
filter: "^aggregation/"
file: bench_aggregation.txt
threshold: "0.99"
- name: expr
filter: "^expr/"
file: bench_expr.txt
threshold: "0.99"
- name: window
filter: "^window/"
file: bench_window.txt
threshold: "0.99"
- name: temporal_metadata
filter: "^temporal_metadata/"
file: bench_temporal_metadata.txt
threshold: "0.99"
- name: udf
filter: "^udf/"
file: bench_udf.txt
threshold: "0.99"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-bench-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-bench-
- name: Restore bench target
uses: actions/cache/restore@v4
with:
path: target
key: ${{ runner.os }}-bench-target-${{ hashFiles('**/Cargo.lock', 'benches/**', 'src/**/*.rs') }}
- name: Run benchmarks (${{ matrix.name }})
run: |
set -o pipefail
CARGO_TERM_COLOR=never cargo bench -- "${{ matrix.filter }}" \
2>&1 | tee ${{ matrix.file }}
- name: Install Bencher CLI
uses: bencherdev/bencher@v0.4.25
- name: Upload to Bencher
id: bencher
continue-on-error: true
run: |
bencher run \
--project minigraf \
--token "${{ secrets.BENCHER_API_TOKEN }}" \
--branch main \
--testbed ubuntu-latest \
--threshold-measure latency \
--threshold-test t_test \
--threshold-upper-boundary ${{ matrix.threshold }} \
--err \
--adapter rust_criterion \
--file ${{ matrix.file }}
- name: Open regression issue
if: steps.bencher.outcome == 'failure'
uses: actions/github-script@v6
with:
script: |
const today = new Date().toISOString().slice(0, 10);
const title = `Benchmark regression - ${today}`;
const { data: openIssues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
labels: 'performance',
state: 'open',
per_page: 100,
});
const existing = openIssues.filter(i =>
i.title.startsWith('Benchmark regression')
);
if (existing.length > 0) {
console.log(`Skipping: open regression issue already exists (#${existing[0].number})`);
return;
}
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: title,
body: [
`Bencher detected a performance regression in the nightly benchmark run (${{ matrix.name }}).`,
'',
`**Run:** ${runUrl}`,
'',
'Please review the Bencher dashboard for details on which benchmarks regressed.',
].join('\n'),
labels: ['performance'],
});