File size: 3,740 Bytes
38be44d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | # CPU Performance Integration Test Harness
## Overview
This directory contains performance/CPU integration tests for the Gemini CLI.
These tests measure wall-clock time, CPU usage, and event loop responsiveness to
detect regressions across key scenarios.
CPU performance is inherently noisy, especially in CI. The harness addresses
this with:
- **IQR outlier filtering** β discards anomalous samples
- **Median sampling** β takes N runs, reports the median after filtering
- **Warmup runs** β discards the first run to mitigate JIT compilation noise
- **15% default tolerance** β won't panic at slight regressions
## Running
```bash
# Run tests (compare against committed baselines)
npm run test:perf
# Update baselines (after intentional changes)
npm run test:perf:update-baselines
# Verbose output
VERBOSE=true npm run test:perf
# Keep test artifacts for debugging
KEEP_OUTPUT=true npm run test:perf
```
## How It Works
### Measurement Primitives
The `PerfTestHarness` class (in `packages/test-utils`) provides:
- **`performance.now()`** β high-resolution wall-clock timing
- **`process.cpuUsage()`** β user + system CPU microseconds (delta between
start/stop)
- **`perf_hooks.monitorEventLoopDelay()`** β event loop delay histogram
(p50/p95/p99/max)
### Noise Reduction
1. **Warmup**: First run is discarded to mitigate JIT compilation artifacts
2. **Multiple samples**: Each scenario runs N times (default 5)
3. **IQR filtering**: Samples outside Q1β1.5ΓIQR and Q3+1.5ΓIQR are discarded
4. **Median**: The median of remaining samples is used for comparison
### Baseline Management
Baselines are stored in `baselines.json` in this directory. Each scenario has:
```json
{
"cold-startup-time": {
"wallClockMs": 1234.5,
"cpuTotalUs": 567890,
"eventLoopDelayP99Ms": 12.3,
"timestamp": "2026-04-08T..."
}
}
```
Tests fail if the measured value exceeds `baseline Γ 1.15` (15% tolerance).
To recalibrate after intentional changes:
```bash
npm run test:perf:update-baselines
# then commit baselines.json
```
### Report Output
After all tests, the harness prints an ASCII summary:
```
βββββββββββββββββββββββββββββββββββββββββββββββββββ
PERFORMANCE TEST REPORT
βββββββββββββββββββββββββββββββββββββββββββββββββββ
cold-startup-time: 1234.5 ms (Baseline: 1200.0 ms, Delta: +2.9%) β
idle-cpu-usage: 2.1 % (Baseline: 2.0 %, Delta: +5.0%) β
skill-loading-time: 1567.8 ms (Baseline: 1500.0 ms, Delta: +4.5%) β
```
## Architecture
```
perf-tests/
βββ README.md β you are here
βββ baselines.json β committed baseline values
βββ globalSetup.ts β test environment setup
βββ perf-usage.test.ts β test scenarios
βββ perf.*.responses β fake API responses per scenario
βββ tsconfig.json β TypeScript config
βββ vitest.config.ts β vitest config (serial, isolated)
packages/test-utils/src/
βββ perf-test-harness.ts β PerfTestHarness class
βββ index.ts β re-exports
```
## CI Integration
These tests are **excluded from `preflight`** and designed for nightly CI:
```yaml
- name: Performance regression tests
run: npm run test:perf
```
## Adding a New Scenario
1. Add a fake response file: `perf.<scenario-name>.responses`
2. Add a test case in `perf-usage.test.ts` using `harness.runScenario()`
3. Run `npm run test:perf:update-baselines` to establish initial baseline
4. Commit the updated `baselines.json`
|