Bench tuning #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Benchmarks | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| paths: | |
| - "src/**" | |
| - "benches/**" | |
| - "Cargo.toml" | |
| - "Cargo.lock" | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| permissions: | |
| contents: write # needed so the benchmark action can push to gh-pages | |
| pull-requests: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| CARGO_INCREMENTAL: 0 | |
| CARGO_PROFILE_DEV_DEBUG: 0 | |
| jobs: | |
| benchmark: | |
| name: Run Benchmarks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: stable | |
| components: rustfmt, clippy | |
| - name: Cache cargo/target | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-bench-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-bench- | |
| ${{ runner.os }}-cargo- | |
| - name: Run benchmarks | |
| run: | | |
| set -euo pipefail | |
| cargo bench --bench ghci_parsing -- --output-format bencher | tee output.txt | |
| cargo bench --bench incremental_reader -- --output-format bencher | tee -a output.txt | |
| cargo bench --bench file_events -- --output-format bencher | tee -a output.txt | |
| cargo bench --bench eval_parsing -- --output-format bencher | tee -a output.txt | |
| cargo bench --bench tui_rendering -- --output-format bencher | tee -a output.txt | |
| # Store historical data on pushes to main (creates gh-pages on first run) | |
| - name: Store benchmark result (main) | |
| if: github.event_name != 'pull_request' | |
| uses: benchmark-action/github-action-benchmark@v1 | |
| with: | |
| name: ghciwatch Benchmarks | |
| tool: cargo | |
| output-file-path: output.txt | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| gh-pages-branch: gh-pages | |
| benchmark-data-dir-path: dev/bench | |
| auto-push: true | |
| # Avoid failing the very first run when gh-pages doesn't exist yet | |
| skip-fetch-gh-pages: true | |
| comment-on-alert: true | |
| alert-threshold: "150%" | |
| save-data-file: true | |
| # On PRs, only try fetching gh-pages if it exists | |
| - name: Check if gh-pages exists | |
| id: ghp | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| if git ls-remote --exit-code origin gh-pages >/dev/null 2>&1; then | |
| echo "exists=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "exists=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Compare benchmarks (PR) | |
| if: github.event_name == 'pull_request' | |
| uses: benchmark-action/github-action-benchmark@v1 | |
| with: | |
| name: ghciwatch Benchmarks | |
| tool: cargo | |
| output-file-path: output.txt | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| gh-pages-branch: gh-pages | |
| benchmark-data-dir-path: dev/bench | |
| auto-push: false | |
| # If gh-pages is missing, skip fetch so the step doesn't fail; it'll still post current results | |
| skip-fetch-gh-pages: ${{ steps.ghp.outputs.exists != 'true' }} | |
| comment-on-alert: true | |
| alert-threshold: "150%" | |
| fail-on-alert: false | |
| comment-always: true | |
| - name: Upload criterion reports | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: criterion-reports | |
| path: target/criterion | |
| retention-days: 30 | |
| benchmark-regression-check: | |
| name: Check for Performance Regressions | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| needs: benchmark | |
| steps: | |
| # Build baseline from main | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: main | |
| fetch-depth: 0 | |
| - name: Install Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: stable | |
| - name: Cache cargo/target (baseline) | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-bench-baseline-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Save baseline (criterion) | |
| run: | | |
| set -euo pipefail | |
| cargo bench --bench ghci_parsing -- --save-baseline main | |
| cargo bench --bench incremental_reader -- --save-baseline main | |
| cargo bench --bench file_events -- --save-baseline main | |
| cargo bench --bench eval_parsing -- --save-baseline main | |
| cargo bench --bench tui_rendering -- --save-baseline main | |
| # Switch to the PR revision | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Run comparison against baseline | |
| run: | | |
| set -euo pipefail | |
| cargo bench --bench ghci_parsing -- --baseline main --output-format bencher | tee comparison.txt | |
| cargo bench --bench incremental_reader -- --baseline main --output-format bencher | tee -a comparison.txt | |
| cargo bench --bench file_events -- --baseline main --output-format bencher | tee -a comparison.txt | |
| cargo bench --bench eval_parsing -- --baseline main --output-format bencher | tee -a comparison.txt | |
| cargo bench --bench tui_rendering -- --baseline main --output-format bencher | tee -a comparison.txt | |
| - name: Comment PR with comparison | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const comparison = fs.readFileSync('comparison.txt', 'utf8'); | |
| const body = [ | |
| '## Benchmark Comparison', | |
| '', | |
| '<details>', | |
| '<summary>Click to expand benchmark results</summary>', | |
| '', | |
| '```', | |
| comparison, | |
| '```', | |
| '', | |
| `View full criterion reports in the workflow run artifacts.`, | |
| '</details>' | |
| ].join('\n'); | |
| await github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body | |
| }); |