first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# Performance Benchmarks
|
||||
|
||||
Microbenchmarks for measuring and tracking performance of critical code paths.
|
||||
|
||||
## When to Use Benchmarks
|
||||
|
||||
**Good fit:**
|
||||
- Hot paths executed thousands of times (expression evaluation, data transforms)
|
||||
- Comparing implementation approaches (current vs proposed)
|
||||
- Detecting regressions in critical code
|
||||
|
||||
**Not a good fit:**
|
||||
- API endpoint latency (use load testing - k6, artillery)
|
||||
- Database query performance (use query analysis tools)
|
||||
- Frontend rendering (use browser profiling)
|
||||
- One-off operations (startup time, migrations)
|
||||
|
||||
**Rule of thumb:** If it runs millions of times per day across all users, benchmark it.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
pnpm --filter=@n8n/performance bench # Run benchmarks
|
||||
pnpm --filter=@n8n/performance bench:baseline # Save baseline for local comparison
|
||||
pnpm --filter=@n8n/performance bench:compare # Compare against baseline (>10% = fail)
|
||||
```
|
||||
|
||||
## CI Regression Detection
|
||||
|
||||
Benchmarks run automatically on PRs that touch `packages/testing/performance/**` or `packages/workflow/src/**`. [CodSpeed](https://codspeed.io) counts CPU instructions instead of wall-clock time, producing deterministic results regardless of runner load. It comments on PRs with results and regression warnings.
|
||||
|
||||
You can also trigger benchmarks manually for any branch via **Actions > Test: Benchmarks > Run workflow**.
|
||||
|
||||
### Local vs CI
|
||||
|
||||
| | Local (`bench`) | CI |
|
||||
|---|---|---|
|
||||
| **Measurement** | Wall-clock time (Hz, ms) | CPU instruction count |
|
||||
| **Noise** | 15-30% variance | Near-zero variance |
|
||||
| **Best for** | Quick sanity checks, comparing approaches | Automated regression detection |
|
||||
|
||||
Local benchmarks are useful for eyeballing performance during development. Use `bench:baseline` + `bench:compare` for before/after comparisons on the same machine in the same session.
|
||||
|
||||
## Adding a Benchmark
|
||||
|
||||
```typescript
|
||||
// benchmarks/my-feature/thing.bench.ts
|
||||
import { bench, describe } from 'vitest';
|
||||
|
||||
// Setup runs once, not measured
|
||||
const data = createTestData();
|
||||
|
||||
describe('My Feature', () => {
|
||||
bench('operation name', () => {
|
||||
doTheThing(data);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Reading Results
|
||||
|
||||
```
|
||||
name hz min max mean p99 rme samples
|
||||
my operation 20,000 0.04 0.20 0.05 0.10 ±0.5% 10000
|
||||
```
|
||||
|
||||
| Column | Meaning |
|
||||
|--------|---------|
|
||||
| hz | Operations per second (higher = faster) |
|
||||
| mean | Average time per operation in ms |
|
||||
| p99 | 99th percentile - worst case latency |
|
||||
| rme | Margin of error - lower = more reliable |
|
||||
| samples | Number of iterations run |
|
||||
|
||||
## Current Benchmarks
|
||||
|
||||
| Area | What it measures | Why it matters |
|
||||
|------|------------------|----------------|
|
||||
| Expression Engine | `={{ }}` evaluation speed | Runs for every node parameter |
|
||||
|
||||
## Notes
|
||||
|
||||
This package pins `vitest@^3.2.0` independently from the monorepo catalog (`^3.1.3`) because CodSpeed requires vitest 3.2+.
|
||||
|
||||
## Tips
|
||||
|
||||
1. **Keep benchmarks focused** - one thing per bench, not workflows
|
||||
2. **Use realistic data sizes** - 100 items is typical, 10k is stress test
|
||||
3. **Compare approaches** - benchmark both before deciding
|
||||
4. **Don't over-benchmark** - only critical hot paths need this
|
||||
Reference in New Issue
Block a user