Skip to content

Add API benchmark system with historical tracking#744

Open
brendanlong wants to merge 1 commit intomasterfrom
claude/593f619f-d495-42c8-ba4e-8fdddd870e39
Open

Add API benchmark system with historical tracking#744
brendanlong wants to merge 1 commit intomasterfrom
claude/593f619f-d495-42c8-ba4e-8fdddd870e39

Conversation

@brendanlong
Copy link
Copy Markdown
Owner

Summary

Closes #743

  • Adds an arewefastyet-style benchmark system that runs concurrent HTTP load against the real tRPC API
  • Includes a data seeder (100K entries, 500 feeds, 3 users), 8 benchmark scenarios (entries.list, markRead, count, subscriptions, sync, tags, entries.get, mixed workload), and a load runner with latency/QPS/error collection
  • Provides memory monitoring via /proc/{pid}/status polling and /usr/bin/time -v peak RSS capture
  • CI workflow runs on master pushes, publishes JSON results to gh-pages branch, with Chart.js dashboard for historical graphs

File structure

benchmarks/
  seed.ts              # Database seeding (100K entries)
  run.ts               # Main orchestrator
  dashboard.html       # Chart.js dashboard
  lib/
    server.ts          # Start/stop Next.js server child process
    http.ts            # tRPC HTTP client (auth, queries, mutations)
    load.ts            # Concurrent load runner with latency collection
    memory.ts          # Memory monitoring via /proc/{pid}/status
    stats.ts           # Percentile calculations
    results.ts         # JSON results I/O
    scenario.ts        # Scenario type definition
  scenarios/
    entries-list.ts    # entries.list with varying filters
    entries-mark-read.ts
    entries-count.ts
    entries-get.ts
    subscriptions-list.ts
    sync-events.ts
    tags-list.ts
    mixed-workload.ts  # Weighted mix simulating real usage
.github/workflows/
  benchmark.yml        # CI workflow (run + publish to gh-pages)

Scripts added

  • pnpm benchmark - Full run (seed + build + bench)
  • pnpm benchmark:seed - Seed only
  • pnpm benchmark:run - Skip seeding (assumes data exists)

Test plan

  • TypeScript typecheck passes
  • Manual run of pnpm benchmark against local DB
  • Verify CI workflow triggers on master push
  • Verify dashboard loads and displays results

🤖 Generated with Claude Code

@gemini-code-assist
Copy link
Copy Markdown

Warning

Gemini encountered an error creating the summary. You can try again by commenting /gemini summary.

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>
@brendanlong brendanlong force-pushed the claude/593f619f-d495-42c8-ba4e-8fdddd870e39 branch from 753aaef to ec68063 Compare April 6, 2026 03:58
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 }}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add API benchmark system with historical tracking

3 participants