# Performance and resource envelopes (1.0) **Status:** measurement recipe + baseline notes (**0.9.7**); large-library UI soak **pass** 2026-08-07 (200+ transcripts); Medium Balanced batch **pass** 2026-08-07 (~9.3 min / 6 transcripts on Docker Compose); thorough full-preset LLM timings on speaker-complete corpus **pass** 2026-08-07 (`qwen2.5:7b`); final Thorough stress pass (2 tx + 2 groups) **pass** 2026-08-08 (corpus **68.7 min**) **Programme:** [pre_release_roadmap_1_0.md](pre_release_roadmap_1_0.md) §12 **Related:** [release_severity_triage_1_0.md](release_severity_triage_1_0.md), [run_performance.md](run_performance.md), [runtime/docker-efficiency-baseline.md](../runtime/docker-efficiency-baseline.md) Documented expectations and regression indicators — not necessarily strict universal guarantees. Capacity failures that corrupt data or hang without recovery are release blockers / must-fix; non-critical misses may ship as known limitations. ## Representative corpus sizes | Class | Working definition | Notes | |-------|-------------------|-------| | Small | 1 short meeting (~2–8 minutes, low segment count) | First useful result / smoke | | Medium | ~5–10 transcripts; default (Balanced) preset | Typical personal corpus | | Large-for-1.0 | ~50 transcripts in library + one multi-member group (3–5 members) | Upper documented expectation for 1.0 | Raw measurement notes may live under ignored `.local/` scratch; curated numbers only below. ## Measurement recipe From repo root on the machine under test (record package version, OS, Docker vs native, CPU/RAM class): ```bash # 1) Package / image identity python -c "import transcriptx; print(transcriptx.__version__)" docker images --digests transcriptx:latest # if Docker profile # 2) Startup (GUI cold) # Time until Home is interactive after `make run` / `./transcriptx.sh` # Record wall seconds. # 3) Import (Small / Medium) # Managed import of N WhisperX/whispermlx JSON transcripts; record wall + disk delta under data root. # 4) Default-preset runtime # Run Balanced (or product default) on Small and Medium; read # /.transcriptx/run_performance.json # and module duration_ms in run_results.json (see run_performance.md). # 5) Time to first useful result # Clock from empty library → import Small → first Overview/Insights paint. # 6) Memory / disk # Peak RSS during Medium default preset; data-root disk before/after. # 7) Model download sizes (optional extras) # Document Hub / spaCy / Ollama pulls from runtime/models.md; do not re-download in CI. # 8) Docker image size docker images transcriptx:latest docker history transcriptx:latest # Compare docs/runtime/docker-efficiency-baseline.md (~3.7GB class historically). # 9) Group scaling # One group of 3–5 Medium-class members; record group wall from group run_performance sidecar. # 10) Insufficient capacity # Note behaviour when disk full / OOM / missing model: must fail closed with recovery path (no corrupt commit). ``` Optional helper (maintainer): ```bash make perf-envelopes # or: python3 scripts/release/perf_envelope_recipe.py ``` Keep notes in `.local/perf_envelopes_.md` (gitignored). Curated numbers only below. ## Metrics checklist | Metric | Status | Expectation / note | |--------|--------|--------------------| | Startup time | measured-or-tagged | Target: interactive Home under ~30s cold on supported Docker/native (known limitation if host-bound) | | Import time | measured-or-tagged | Small: seconds–low tens; Medium scales ~linear with file count | | Time to first useful result | measured-or-tagged | Small path should complete without undocumented steps | | Default-preset runtime | measured | Medium Balanced **pass** 2026-08-07 — 6 transcripts, batch wall ~9.3 min, all succeeded (see [manual_acceptance_1_0.md](manual_acceptance_1_0.md) §3.12). Thorough full-preset + local LLM (`qwen2.5:7b`) on speaker-complete corpus: see § Thorough full-preset LLM timings + § Final Thorough stress pass below. | | Memory and disk use | measured-or-tagged | Record peak RSS + data-root delta; OOM without recovery = blocker | | Model download sizes | documented | See [runtime/models.md](../runtime/models.md); first-run download is expected when enabled | | Docker image size | documented baseline | Historical ~3.7GB class — [docker-efficiency-baseline.md](../runtime/docker-efficiency-baseline.md); re-measure on release hardware | | Group-analysis scaling | measured-or-tagged | Group wall ≠ sum of members; includes aggregation | | UI responsiveness with large library | measured | **pass** 2026-08-07 — Home/library responsive with **200+** transcripts (exceeds Large-for-1.0 ~50); see [manual_acceptance_1_0.md](manual_acceptance_1_0.md) §3.12 | | Behaviour when disk/RAM/model insufficient | must document | Fail closed; no corrupt run commit; actionable GUI/docs errors | ## Thorough full-preset LLM timings (2026-08-07) **Scope:** every managed transcript whose speaker map is **complete** (every diarized ID named or ignored). After a local `schema_version` `"1.0"` → `1` patch so the files load under the integer-1 epoch, that set is: | Transcript | Segments | Speakers | Duration | Status | |------------|---------:|---------:|---------:|--------| | `260615_Ana_phd_presentation_QA.json` | 297 | 10 | ~28 min | complete | | `260615_Ana_phd_supervision_meeting.json` | 450 | 3 | ~36 min | complete | (`_deep_test_large_norm` remains **partial** — 1 unidentified speaker — and was excluded. Mini / fixture transcripts are `none` / incomplete.) **Environment:** native host Python `0.9.8.7`, Apple Silicon / host Ollama, shared model **`qwen2.5:7b`** (~7.6B, Q4_K_M; project-recommended ~6–8B class). Mode=`full`, modules=`None` (default full set including LLM consumers + `chart_descriptions` finalize). ### Results | Transcript | Wall | DAG | `chart_descriptions` finalize | Final status | Notes | |------------|-----:|----:|-------------------------------:|--------------|-------| | Presentation QA (initial) | **71.4 min** (4283 s) | 53.3 min | 18.1 min | **partial** | 4 LLM modules timed out at 600 s each while Ollama still held `qwen3-vl:8b` (~44 GB). Soft-fail continued the pipeline. | | Presentation QA (LLM retry) | **32 s** | n/a | n/a | **succeeded** | Retried only `llm_action_items` / `llm_speaker_summary` / `llm_summary` / `narrative_summary` with free Ollama — all green (3–6 s each). | | Supervision meeting | **10.1 min** (606 s) | 3.9 min | 6.1 min | **succeeded** | 42 modules, 0 errors. Clean run with `qwen2.5:7b` resident. | | **Corpus effective sum** | **~42.0 min** | — | — | composite | QA effective (~31.9 min = initial − 2400 s timeout dead time + retry) + supervision 10.1 min | ### LLM consumer timings (clean Ollama / `qwen2.5:7b`) | Module | Presentation QA (retry) | Supervision | |--------|------------------------:|------------:| | `llm_action_items` | 6.0 s | 7.0 s | | `llm_speaker_summary` | 5.7 s | 6.5 s | | `llm_summary` | 3.2 s | 2.9 s | | `narrative_summary` | 5.7 s | 3.0 s | | `topic_shift` | (545 s under contention in initial QA) | 13.6 s | | `chart_descriptions` | ~18 min (197-class chart set; initial QA) | ~6.1 min | ### Regression / ops notes - **Ollama contention is a first-class risk:** a resident multi-GB vision model can push LLM modules into the 600 s soft-timeout path and inflate wall clock by ~40 minutes even though non-LLM work is fine. Documented expectation: keep the intended chat model loaded (or unload others) before thorough LLM runs; treat multi-model contention hangs as capacity / ops, not analysis correctness failures when the circuit-breaker soft-fails. - **`chart_descriptions` dominate thorough walls** once LLM chat modules are healthy (often longer than the entire DAG on chart-heavy transcripts). - Machine-readable copies: `artifacts/roadmap_1_0_llm_analysis/corpus_timings.json`, `qa_timings.json`, plus run logs / `thorough_named_speaker_corpus.md`. Private mirror: `.local/release_evidence/20260807_thorough_qwen25_7b/`. Run dirs: `…/260615_Ana_phd_presentation_QA/20260807_171909_15949872` (+ retry `…/20260807_232957_38197390`), `…/260615_Ana_phd_supervision_meeting/20260807_233852_38732557`. ## Final Thorough stress pass (2026-08-08) **Scope:** same speaker-complete transcript rule as above, **plus** every group whose members are all speaker-complete. Qualifying set on this host: 2 transcripts + 2 groups (`_deep_test_bertopic_group2`, `Perf smoke Ana multi-speaker` — identical Ana member pair). **Environment:** native host Python `0.9.8.8` / git `3b206e3`, Apple Silicon / host Ollama, shared model **`qwen2.5:7b`** only (no vision contention). Preset=`thorough` (42 suitable modules including BERTopic + LLM consumers + `chart_descriptions`). ### Results | Run | Wall | Final status | Notes | |-----|-----:|--------------|-------| | Presentation QA | **9.8 min** (585.5 s) | **succeeded** | 42 modules / 0 failures; DAG ~199 s; `chart_descriptions` est ~6.4 min; LLM 4/4 calls / 15.3 s logical | | Supervision meeting | **10.9 min** (651.9 s) | **succeeded** | 42 modules / 0 failures; DAG ~261 s; `chart_descriptions` est ~6.5 min; LLM 5/5 calls / 44.1 s logical | | Group `_deep_test_bertopic_group2` | **24.0 min** (1442.6 s) | **succeeded** | both members + aggregation + group charts | | Group `Perf smoke Ana multi-speaker` | **24.0 min** (1439.4 s) | **succeeded** | same members; independent group run | | **Corpus sum** | **68.7 min** (4119.4 s) | **passed** | transcripts 20.6 + groups 48.0 | Clean-Ollama transcript walls are ~4× faster than the contended 2026-08-07 presentation QA probe; group walls are ~2.3× the two-transcript sum (member re-analysis + aggregation + group `chart_descriptions`). ### Artifacts - Scratch: `artifacts/roadmap_1_0_llm_analysis/stress_pass_20260808/` (`SUMMARY.md`, `batch_summary.json`, `corpus_timings.json`, `batch.log`) - Private mirror: `.local/release_evidence/20260808_thorough_stress_pass/` - Run dirs: `…/260615_Ana_phd_presentation_QA/20260808_151213_94733139`, `…/260615_Ana_phd_supervision_meeting/20260808_152158_95318679`, `…/groups/7b9c6531-…/20260808_135224_e1985784`, `…/groups/bba6641e-…/20260808_141623_8a279f84` ## UI Docker Thorough batch — partial / stalled (2026-08-09) **Scope:** Streamlit Batch Analysis via Docker Compose on the mounted managed library (not the native speaker-complete stress corpus above). Preset = Thorough (**41** modules). Live LLM **`gemma3:4b`**. Package `0.9.8.9`. **Outcome:** **stalled** — incomplete; do not treat as a Thorough envelope pass. | Phase | Wall | Status | Notes | |-------|-----:|--------|-------| | 10 skip-heavy library-head transcripts | **~2.1 min** sum | succeeded | Unnamed-speaker gates → mostly SKIP; ~9–16 s each | | First full Thorough transcript (`tx-full-01`) | **~18 min** | artifacts written; batch did not advance | 41/41 modules, 0 failures; **197/197** `chart_descriptions` | | Batch remainder | — | **stalled** | No next pipeline start after `tx-full-01`; `.run_finalization.lock` left; `.transcriptx/run_performance.json` missing | **Ops notes:** UI Thorough on a mixed library is skip-heavy until named-speaker rows; long `chart_descriptions` is a batch-resilience risk (logs look finished while the queue hangs). An earlier Balanced UI kick the same evening was aborted as the wrong preset. **Artifacts:** `artifacts/roadmap_1_0_llm_analysis/ui_thorough_batch_20260809/` (anonymised labels only) · private mirror `.local/release_evidence/20260809_ui_docker_thorough_batch/` ## Recording Record measured values per environment (Docker vs native) in release-evidence notes when claiming envelopes. Soft-cut for 0.9.7 allows recipe + tagged gaps; RC prefers filled Small/Medium rows on release hardware.