name: Benchmarks
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: write
pull-requests: write
env:
CARGO_TERM_COLOR: always
jobs:
benchmark-main:
name: Benchmark (main)
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 2
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install critcmp
run: cargo install critcmp
- name: Cache cargo registry and build
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-bench-${{ hashFiles('**/Cargo.lock', '**/Cargo.toml') }}
restore-keys: |
${{ runner.os }}-cargo-bench-
- name: Run benchmarks on current commit
run: cargo bench --features decimal --bench benchmarks -- --noplot --save-baseline current
- name: Checkout previous commit
run: git checkout HEAD~1
- name: Run benchmarks on previous commit
run: cargo bench --features decimal --bench benchmarks -- --noplot --save-baseline previous
- name: Compare benchmarks
run: |
echo "## Benchmark Comparison (vs previous commit)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Comparing \`${{ github.sha }}\` against previous commit" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
critcmp previous current >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
- name: Upload benchmark results
uses: actions/upload-artifact@v4
with:
name: benchmark-results-${{ github.sha }}
path: target/criterion
retention-days: 30
benchmark-pr:
name: Benchmark (PR)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install critcmp
run: cargo install critcmp
- name: Cache cargo registry and build
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-bench-${{ hashFiles('**/Cargo.lock', '**/Cargo.toml') }}
restore-keys: |
${{ runner.os }}-cargo-bench-
- name: Run benchmarks on PR branch
run: cargo bench --features decimal --bench benchmarks -- --noplot --save-baseline pr
- name: Checkout base branch
run: git checkout ${{ github.base_ref }}
- name: Run benchmarks on base branch
run: cargo bench --features decimal --bench benchmarks -- --noplot --save-baseline base
- name: Compare benchmarks
run: |
echo "## Benchmark Comparison (PR vs ${{ github.base_ref }})" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
critcmp base pr >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const { execSync } = require('child_process');
const output = execSync('critcmp base pr', { encoding: 'utf-8' });
const body = `## 📊 Benchmark Comparison
<details>
<summary>Click to expand benchmark results</summary>
\`\`\`
${output}
\`\`\`
</details>
> Compared against \`${{ github.base_ref }}\` branch
`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('Benchmark Comparison')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}