Repository navigation
perf: establish truthful performance baseline (Phase 1) #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
70781ca
fix: ignore pi
heynemann 48a40a9
docs: add batcher performance and reliability plan
heynemann 11d55ad
test: fix and scope enqueue microbenchmarks
heynemann e2946e5
test: add open-loop scenario harness
heynemann c8cd935
ci: add performance guard lanes and predeclared thresholds
heynemann bce5270
ci: exclude scenario harness from coverage thresholds
heynemann 5d668db
test: move scenario harness to test/scenario and derive host-sensitiv…
heynemann 6d06a7c
fix: address PR review findings on the performance baseline
heynemann e3b2d90
fix: exclude test directories from coverage action
heynemann 5e6193d
docs: document the measurement baseline for contributors
heynemann 455e27d
ci: restore build, test, coverage and lint checks
heynemann d3e2059
test: correct scenario metric semantics and harden the allocation gate
heynemann e508252
fix: correct Phase 1 scenario peaks and benchmark commands
heynemann File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,113 +1,92 @@ | ||
| --- | ||
| # Build, unit tests, coverage, vet, and formatting. | ||
| # | ||
| # This workflow intentionally uses only first-party actions/* steps and plain Go | ||
| # commands. The prior Go workflow has been failing at startup on main since | ||
| # 2026-04-22, before any job is created. Its YAML validates and every referenced | ||
| # action resolves, pointing at a repository or organisation Actions policy issue | ||
| # around its third-party actions (super-linter, go-test-report, go-coverage-action, | ||
| # codeclimate-action), not a code failure. Replacing it in place restores the build, | ||
| # unit-test, coverage, lint and formatting checks pull requests are meant to have. | ||
| # | ||
| # Do not filter pull_request by base branch. Stacked PRs target the layer below | ||
| # rather than main; a `branches: [main]` filter skips every layer above the bottom. | ||
| name: Go | ||
| on: | ||
| push: | ||
| branches: ["main"] | ||
| pull_request: | ||
| branches: ["main"] | ||
| permissions: read-all | ||
| workflow_dispatch: | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| build: | ||
| permissions: | ||
| contents: read | ||
| packages: read | ||
| # To report GitHub Actions status checks | ||
| statuses: write | ||
| name: Build | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Set up Go | ||
| uses: actions/setup-go@v4 | ||
| - name: Build | ||
| run: go build -v ./... | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| go-version-file: go.mod | ||
| - run: go build -v ./... | ||
| test: | ||
| permissions: | ||
| contents: read | ||
| packages: read | ||
| # To report GitHub Actions status checks | ||
| statuses: write | ||
| name: Unit tests | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Set up Go | ||
| uses: actions/setup-go@v4 | ||
| - uses: brian-pickens/go-test-report@v1 | ||
| with: | ||
| packages: "./..." | ||
| summary: "true" | ||
| coverage: | ||
| permissions: | ||
| contents: write | ||
| checks: write | ||
| issues: write | ||
| pull-requests: write | ||
| # To report GitHub Actions status checks | ||
| statuses: write | ||
| persist-credentials: false | ||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| go-version-file: go.mod | ||
| - name: Run tests | ||
| run: go test -v ./... | ||
| vet: | ||
| name: Vet and formatting | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Set up Go | ||
| uses: actions/setup-go@v4 | ||
| - name: Set up Node.js (for coverage) | ||
| uses: actions/setup-node@master | ||
| with: | ||
| node-version: "12" | ||
| - name: setup tsc | ||
| run: npm install -g typescript | ||
| - name: Gather dependencies | ||
| run: go mod download | ||
| - uses: gwatts/go-coverage-action@v2 | ||
| id: coverage | ||
| persist-credentials: false | ||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| coverage-threshold: 80 | ||
| cover-pkg: ./... | ||
| ignore-pattern: | | ||
| \.pb\.go$ | ||
| \_string\.go$ | ||
| \main\.go$ | ||
| \internal\/test\/.*$ | ||
| - name: Generate coverage tree map | ||
| go-version-file: go.mod | ||
| - name: go vet | ||
| run: go vet ./... | ||
| - name: gofmt | ||
| run: | | ||
| go run github.com/nikolaydubina/go-cover-treemap@latest \ | ||
| -coverprofile ${{ steps.coverage.outputs.gocov-agg-pathname }} \ | ||
| -only-folders=true >/tmp/treemap.svg | ||
| - uses: paambaati/codeclimate-action@v6.0.0 | ||
| env: | ||
| CC_TEST_REPORTER_ID: ${{ secrets.CODECLIMATE_TOKEN }} | ||
| with: | ||
| coverageCommand: make coverage-report-ci | ||
| prefix: github.com/NSXBet/batcher | ||
| coverageLocations: | | ||
| ${{github.workspace}}/coverage.txt:gocov | ||
| lint: | ||
| permissions: | ||
| contents: read | ||
| packages: read | ||
| # To report GitHub Actions status checks | ||
| statuses: write | ||
| unformatted="$(gofmt -l pkg internal test)" | ||
| if [ -n "$unformatted" ]; then | ||
| echo "These files are not gofmt-formatted:" | ||
| echo "$unformatted" | ||
| exit 1 | ||
| fi | ||
| coverage: | ||
| name: Coverage | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - name: Super-linter | ||
| uses: nsx-actions/super-linter_super-linter@v6.6.0 | ||
| env: | ||
| # To report GitHub Actions status checks | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| VALIDATE_GO: false | ||
| VALIDATE_JSCPD: false | ||
| go-action-detection: | ||
| permissions: | ||
| contents: write | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: "Checkout Repository" | ||
| uses: actions/checkout@v3 | ||
| - uses: actions/setup-go@v3 | ||
| with: | ||
| go-version: ">=1.22.0" | ||
| - name: Run snapshot action | ||
| uses: actions/go-dependency-submission@v2 | ||
| persist-credentials: false | ||
| - uses: actions/setup-go@v6 | ||
| with: | ||
| go-mod-path: go.mod | ||
| go-version-file: go.mod | ||
| - name: Measure coverage | ||
| # The scenario harness under test/ is measurement infrastructure, not | ||
| # shipped code, so it is excluded from the enforced number for the same | ||
| # reason internal/test is. | ||
| run: | | ||
| go test -coverprofile=coverage.out ./... | ||
| grep -v '/test/' coverage.out > coverage-filtered.out | ||
| go tool cover -func=coverage-filtered.out | tail -1 | ||
| - name: Enforce threshold | ||
| run: | | ||
| threshold=80 | ||
| total="$(go tool cover -func=coverage-filtered.out \ | ||
| | tail -1 | awk '{print $3}' | tr -d '%')" | ||
| echo "shipped-code coverage: ${total}% (threshold ${threshold}%)" | ||
| awk -v t="$threshold" -v c="$total" \ | ||
| 'BEGIN { exit (c + 0 >= t + 0) ? 0 : 1 }' \ | ||
| || { echo "coverage ${total}% is below ${threshold}%"; exit 1; } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| --- | ||
| name: Performance | ||
| on: | ||
| pull_request: | ||
| branches: ["main"] | ||
| push: | ||
| branches: ["main"] | ||
| schedule: | ||
| # Weekly full matrix. Latency is reported here, never gated. | ||
| - cron: "0 3 * * 1" | ||
| workflow_dispatch: | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| # Blocking lane. Gates only on signals that are stable on shared runners: | ||
| # correctness under the race detector and exact allocation counts. | ||
| # Latency percentiles are deliberately NOT gated here, because measured spread | ||
| # on GitHub-hosted runners has exceeded the difference between configurations. | ||
| guards: | ||
| name: Race and allocation guards | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Set up Go | ||
| uses: actions/setup-go@v6 | ||
| with: | ||
| go-version-file: go.mod | ||
| - name: Race detector | ||
| run: go test -race ./... | ||
| - name: Allocation gates | ||
| # Thresholds are predeclared in docs/improvements/thresholds.md. | ||
| # | ||
| # A -run substring that matches nothing exits 0, which would silently drop | ||
| # this gate if a test were renamed. Assert the expected tests actually ran. | ||
| run: | | ||
| go test -run 'Alloc' -count=1 -v ./... 2>&1 | tee /tmp/alloc-gate.txt | ||
| for want in TestAddAllocatesNothingPerCall \ | ||
| TestHarnessRecorderDoesNotAllocatePerItem; do | ||
| if ! grep -q -- "--- PASS: $want" /tmp/alloc-gate.txt; then | ||
| echo "allocation gate did not run $want -- was it renamed?" | ||
| exit 1 | ||
| fi | ||
| done | ||
| - name: Enqueue microbenchmarks compile and run | ||
| run: | | ||
| go test -run='^$' -bench='BenchmarkBatcherEnqueue' \ | ||
| -benchtime=100x -benchmem ./pkg/batcher | ||
| # Reporting lane. Produces the evidence used to choose a default batch window. | ||
| # Informational by design: it must never fail a pull request on timing. | ||
| matrix: | ||
| name: Scenario matrix (informational) | ||
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Set up Go | ||
| uses: actions/setup-go@v6 | ||
| with: | ||
| go-version-file: go.mod | ||
| - name: Record environment | ||
| run: | | ||
| { | ||
| echo "date: $(date -u +%Y-%m-%dT%H:%M:%SZ)" | ||
| echo "go: $(go version)" | ||
| echo "runner: ${{ runner.os }} ${{ runner.arch }}" | ||
| echo "nproc: $(nproc)" | ||
| echo "gomaxprocs: $(go env GOMAXPROCS)" | ||
| echo "cpu: $(awk -F': ' '/^model name/{print $2; exit}' /proc/cpuinfo)" | ||
| echo "commit: ${{ github.sha }}" | ||
| } > environment.txt | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| cat environment.txt | ||
| - name: Scenario matrix | ||
| env: | ||
| SCENARIO_MATRIX: "1" | ||
| run: | | ||
| go test -run TestScenarioMatrix -timeout 40m -v ./test/scenario/ \ | ||
| | tee scenario-matrix.txt | ||
| # Produces benchstat input, but does not compare: no baseline recorded on this | ||
| # runner exists yet, and comparing against a developer machine's numbers would | ||
| # be meaningless. Trend comparison is deferred until a scheduled run has | ||
| # stored an ubuntu-latest/amd64 baseline. See docs/improvements/thresholds.md. | ||
| - name: Enqueue benchmarks with benchstat input | ||
| run: | | ||
| go test -run='^$' -bench='BenchmarkBatcherEnqueue' -benchmem \ | ||
| -benchtime=2s -count=10 -cpu=1,2,4 ./pkg/batcher \ | ||
| | tee enqueue-bench.txt | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| - name: Upload performance artifacts | ||
| if: ${{ always() }} | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: performance-report | ||
| path: | | ||
| environment.txt | ||
| scenario-matrix.txt | ||
| enqueue-bench.txt | ||
| retention-days: 90 | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,3 +27,4 @@ dist | |
| .mcp.json | ||
| .claude-flow | ||
| .swarm | ||
| .pi | ||
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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.