You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
test: gate memory-path benchmarks in baselines (parse + ZIP export) (#97)
* test: gate memory-path benchmarks in baselines (parse + ZIP export)
* fix(ci): seed ubuntu baselines and fix ruff/mypy benchmark regressions
* fix(test): harden benchmark gate and tracemalloc fixtures (PR review)
* fix(ci): ruff format check_benchmark_regression.py
* tests/benchmarks/conftest.py for i in range(count): write_jsonl(project / f"session_{i:04d}.jsonl", 20) # Unique first_timestamp per session so export filenames do not collide in ZIP benches. first_ts = f"2026-06-12T{i % 24:02d}:{i % 60:02d}:00Z" @timon0305 timon0305 1 minute ago Member first_ts = f"2026-06-12T{i % 24:02d}:{i % 60:02d}:00Z" is only unique for count ≤ 120 (collides at lcm(24,60)). Add assert count <= 120 (or a wider format) so a future corpus bump can't produce colliding ZIP entries.
* fix(test): align baseline refresh slack and export timestamp rollover
| parse |`parse_session` on 10 / 500 / 5000+ line JSONL; large-file peak heap (`test_parse_large_peak_memory`)|
27
+
| export |`run_bulk_export`latency over 10 / 50 / 100 sessions; ZIP export peak heap (`test_bulk_export_zip_peak_memory`)|
28
28
| search |`GET /api/search` over a 50-session synthetic corpus |
29
29
| cache | cold vs warm `get_cached_session` (informational; not gated) |
30
30
31
31
Large JSONL files (5000+ lines) are generated at test session scope under pytest's temp directory — not committed to git.
32
32
33
33
Corpora repeat one row from `tests/fixtures/session_with_tools.jsonl`, so parse/export numbers measure steady-state throughput on a narrow schema slice — not full parser branch coverage. Treat as v1 baselines, not exhaustive perf proof.
34
34
35
-
The memory test (`test_parse_memory.py`) is intentionally **not** skipped by `--benchmark-skip`; it runs in the main `pytest` job and builds the session-scoped 5000-line fixture once per session.
35
+
The memory ceiling test (`test_large_parse_peak_memory_under_ceiling`) runs in the main `pytest` job. Tracked peak-memory benchmarks (`test_parse_large_peak_memory`, `test_bulk_export_zip_peak_memory`) run under `--benchmark-only` and store `extra_info.peak_bytes` for the regression gate.
36
36
37
37
## CI gate
38
38
39
39
The `benchmarks` job on **ubuntu-latest** runs pytest-benchmark (`--benchmark-json=benchmark-results.json`), then `scripts/check_benchmark_regression.py benchmark-results.json benchmarks/baselines.json`. CI fails when any **gated** benchmark mean exceeds its baseline by more than **20%**.
**Gated:** parse medium/large + large peak memory; export 10/50/100 session latency + ZIP peak memory.
42
42
43
-
**Not gated (informational only):**`test_parse_session_small`, `test_search_full_corpus` (sub-ms CI noise), and the `cache` group. Benchmarks without a baseline entry print a warning and do not fail the gate.
43
+
**Not gated (informational only):**`test_parse_session_small`, `test_search_full_corpus` (sub-ms CI noise), and the `cache` group. These may appear in `baselines.json` for reference but are skipped by `check_benchmark_regression.py`. Benchmarks without a baseline entry print a warning and do not fail the gate.
44
+
45
+
Missing gated benchmarks (renamed or removed tests still listed in `baselines.json`) fail the gate.
44
46
45
47
## Refresh baselines
46
48
47
-
After intentional performance work, capture on **ubuntu-latest** (same OS as the gated CI job):
49
+
After intentional performance work, capture on **ubuntu-latest** (same OS as the gated CI job). Download `benchmark-results.json` from a CI artifact when possible:
For a quick local snapshot only (may not match CI timings):
48
56
49
57
```bash
50
-
make update-baselines
58
+
make seed-baselines-local
51
59
```
52
60
61
+
`make update-baselines` is a deprecated alias for `seed-baselines-local` and prints a warning. Do not commit baselines from macOS/Windows unless you accept cross-OS gate skew.
Baselines must be captured on **ubuntu-latest** to match the gated CI runner. Cross-OS variance causes spurious failures. Download `benchmark-results.json` from a CI artifact to seed baselines if needed.
70
+
Baselines must be captured on **ubuntu-latest** to match the gated CI runner. Cross-OS variance causes spurious failures.
"_note": "Gated means from ubuntu-latest CI benchmark-results.json (post-cache PR #90). Excluded from gate: test_parse_session_small, test_search_full_corpus (sub-ms CI noise). Refresh via make update-baselines on ubuntu.",
3
-
"updated": "2026-06-17T21:00:00Z",
2
+
"_note": "Gated means from ubuntu-latest CI benchmark-results.json (PR #97, run 28126772276). Excluded from gate (recorded for reference): test_parse_session_small, test_search_full_corpus (sub-ms CI noise). Memory benchmarks use extra_info.peak_bytes (bytes); latency uses stats.mean (seconds).",
0 commit comments