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`