f99010fae1
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Windows) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Has been cancelled
98 lines
3.9 KiB
YAML
98 lines
3.9 KiB
YAML
name: Bench Gate
|
|
|
|
# Compares hot-path benchmarks between the PR head and its merge
|
|
# base, so performance regressions in the sync engine and DB write
|
|
# paths fail the PR instead of shipping. The gated regression classes
|
|
# have all shipped before:
|
|
#
|
|
# - discovery/skip work scaling with archive size instead of new
|
|
# data (#912, the providerSourceUnchangedInDB gap)
|
|
# - O(session history) work per incremental append (#954)
|
|
# - bulk ingest throughput (#411)
|
|
# - per-row query-shape regressions in usage aggregation (#309)
|
|
#
|
|
# Both sides run `make bench-gate` — the Makefile is the single
|
|
# source of truth for the gated package list, sample count, and
|
|
# iteration count — and cmd/benchgate compares the outputs. It gates
|
|
# on allocs/op and B/op (deterministic on a given machine, tight
|
|
# thresholds) and on ns/op with a loose 2x threshold that only
|
|
# catches algorithmic blowups; both sides run on the same runner
|
|
# within one job, so the comparison is apples to apples.
|
|
#
|
|
# Benchmarks that only exist on one side are reported but never fail
|
|
# the gate: a benchmark added by a PR has no baseline and is reported
|
|
# without gating, then gates automatically once merged. Because each
|
|
# side benchmarks its own Makefile's package list, a PR that adds a
|
|
# package to the gate cannot break the base run. A partially failing
|
|
# base run degrades to a partial baseline (whatever benchmarks it
|
|
# produced still gate) rather than silently disabling the whole gate.
|
|
|
|
on:
|
|
pull_request:
|
|
# Docs/frontend-only PRs cannot change the gated Go paths. If
|
|
# this check is ever made required on branch protection, pair it
|
|
# with a no-op sibling workflow on the inverse paths.
|
|
paths:
|
|
- "**.go"
|
|
- "go.mod"
|
|
- "go.sum"
|
|
- "Makefile"
|
|
- ".github/workflows/bench.yml"
|
|
|
|
concurrency:
|
|
group: bench-${{ github.head_ref || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
bench-gate:
|
|
name: Benchmark Gate
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
fetch-depth: 0
|
|
|
|
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
|
with:
|
|
go-version-file: go.mod
|
|
|
|
- name: Run benchmarks (PR head)
|
|
run: |
|
|
set -euo pipefail
|
|
make -s bench-gate | tee /tmp/bench-new.txt
|
|
|
|
- name: Run benchmarks (merge base)
|
|
env:
|
|
BASE_REF: ${{ github.base_ref }}
|
|
# A failing merge-base run keeps whatever benchmark output it
|
|
# produced: go test emits results per package, so one broken
|
|
# package (or a base predating the bench-gate target) leaves
|
|
# a partial or empty baseline and benchgate gates only what
|
|
# exists on both sides. The warning makes the degraded run
|
|
# visible instead of a silently green vacuous pass.
|
|
#
|
|
# The sample count and fixed iteration count are evaluated
|
|
# from the PR head's Makefile and passed into the base run:
|
|
# two benchmarks grow their fixture per iteration, so a PR
|
|
# that changes BENCH_GATE_COUNT/TIME must not compare against
|
|
# a baseline measured with the old values. The package list
|
|
# intentionally stays per-side, so growing the gate cannot
|
|
# break the base run.
|
|
run: |
|
|
set -euo pipefail
|
|
eval "$(make -s bench-gate-config)"
|
|
base=$(git merge-base HEAD "origin/$BASE_REF")
|
|
git worktree add /tmp/bench-base "$base"
|
|
if ! make -s -C /tmp/bench-base bench-gate \
|
|
BENCH_GATE_COUNT="$BENCH_GATE_COUNT" \
|
|
BENCH_GATE_TIME="$BENCH_GATE_TIME" > /tmp/bench-old.txt; then
|
|
echo "::warning title=Bench Gate::merge-base benchmark run exited non-zero; gating against its partial output"
|
|
fi
|
|
|
|
- name: Compare against merge base
|
|
run: go run ./cmd/benchgate -old /tmp/bench-old.txt -new /tmp/bench-new.txt
|