Add API benchmark system with historical tracking#744
Open
brendanlong wants to merge 1 commit intomasterfrom
Open
Add API benchmark system with historical tracking#744brendanlong wants to merge 1 commit intomasterfrom
brendanlong wants to merge 1 commit intomasterfrom
Conversation
|
Warning Gemini encountered an error creating the summary. You can try again by commenting |
Implements an arewefastyet-style benchmark system that hits the real HTTP
API under concurrent load, produces structured JSON results, and provides
a Chart.js dashboard for tracking performance over time.
Components:
- Data seeder: 100K entries across 500 feeds, 3 users with realistic data
- Load runner: Custom concurrency controller with latency collection
- 8 benchmark scenarios (entries.list, markRead, count, subscriptions,
sync, tags, entries.get, mixed workload)
- Memory monitoring via /proc/{pid}/status polling + /usr/bin/time -v
- CI workflow: runs on master pushes, publishes results to gh-pages
- Dashboard: Chart.js graphs for latency/QPS/RSS/errors over commits
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
753aaef to
ec68063
Compare
Comment on lines
+15
to
+116
| runs-on: ubuntu-latest | ||
| timeout-minutes: 30 | ||
|
|
||
| services: | ||
| postgres: | ||
| image: postgres:16 | ||
| env: | ||
| POSTGRES_DB: benchmark | ||
| POSTGRES_USER: benchmark | ||
| POSTGRES_PASSWORD: benchmark | ||
| ports: | ||
| - 5432:5432 | ||
| options: >- | ||
| --health-cmd pg_isready | ||
| --health-interval 10s | ||
| --health-timeout 5s | ||
| --health-retries 5 | ||
| redis: | ||
| image: redis:7 | ||
| ports: | ||
| - 6379:6379 | ||
| options: >- | ||
| --health-cmd "redis-cli ping" | ||
| --health-interval 10s | ||
| --health-timeout 5s | ||
| --health-retries 5 | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: pnpm/action-setup@v4 | ||
|
|
||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 22 | ||
| cache: pnpm | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Run database migrations | ||
| run: pnpm db:migrate | ||
| env: | ||
| DATABASE_URL: postgresql://benchmark:benchmark@localhost:5432/benchmark | ||
|
|
||
| - name: Run benchmarks | ||
| run: pnpm benchmark | ||
| env: | ||
| DATABASE_URL: postgresql://benchmark:benchmark@localhost:5432/benchmark | ||
| REDIS_URL: redis://localhost:6379 | ||
| NODE_ENV: production | ||
| timeout-minutes: 20 | ||
|
|
||
| - name: Upload results as artifact | ||
| uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: benchmark-results-${{ github.sha }} | ||
| path: benchmarks/results/*.json | ||
| retention-days: 90 | ||
|
|
||
| - name: Publish to GitHub Pages | ||
| if: success() && github.ref == 'refs/heads/master' | ||
| run: | | ||
| # Configure git | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | ||
|
|
||
| # Get the result file | ||
| RESULT_FILE=$(ls benchmarks/results/*.json | head -1) | ||
| RESULT_BASENAME=$(basename "$RESULT_FILE") | ||
|
|
||
| # Switch to gh-pages branch (create if needed) | ||
| git fetch origin gh-pages || true | ||
| git checkout gh-pages 2>/dev/null || git checkout --orphan gh-pages | ||
|
|
||
| # Ensure results directory exists | ||
| mkdir -p results | ||
|
|
||
| # Copy new result | ||
| git checkout "${{ github.sha }}" -- benchmarks/results/"$RESULT_BASENAME" 2>/dev/null || true | ||
| cp benchmarks/results/"$RESULT_BASENAME" results/ 2>/dev/null || cp "$RESULT_FILE" results/ | ||
|
|
||
| # Copy dashboard | ||
| git checkout "${{ github.sha }}" -- benchmarks/dashboard.html 2>/dev/null || true | ||
| cp benchmarks/dashboard.html index.html 2>/dev/null || true | ||
|
|
||
| # Update index.json manifest | ||
| node -e " | ||
| const fs = require('fs'); | ||
| const dir = 'results'; | ||
| const files = fs.readdirSync(dir).filter(f => f.endsWith('.json') && f !== 'index.json').sort(); | ||
| fs.writeFileSync(dir + '/index.json', JSON.stringify({ files }, null, 2)); | ||
| " | ||
|
|
||
| # Commit and push | ||
| git add results/ index.html | ||
| git commit -m "Update benchmark results for ${{ github.sha }}" || echo "No changes to commit" | ||
| git push origin gh-pages || echo "Failed to push to gh-pages" | ||
|
|
||
| # Return to original branch | ||
| git checkout "${{ github.sha }}" |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Closes #743
/proc/{pid}/statuspolling and/usr/bin/time -vpeak RSS capturegh-pagesbranch, with Chart.js dashboard for historical graphsFile structure
Scripts added
pnpm benchmark- Full run (seed + build + bench)pnpm benchmark:seed- Seed onlypnpm benchmark:run- Skip seeding (assumes data exists)Test plan
pnpm benchmarkagainst local DB🤖 Generated with Claude Code