# Phase 0 – Performance-Baseline (Shinkan Jinkendo) **Zweck:** Reproduzierbarer Startpunkt **vor** Phase 2 (Backend-Lesepfade, Summary-API). **Stand:** 2026-05-13 · Backend-App-Version laut `backend/version.py`: **0.8.110** Nach grösseren Deployments oder Schema-Änderungen: Bundle-Abschnitt neu erfassen (`npm run build`); API-/k6-Werte bei Bedarf aktualisieren. --- ## 1. Frontend-Bundle (`npm run build`) Messung: Repo-Root → `cd frontend && npm run build` (Vite Production). **Hinweis:** Dateinamen mit Hash (`index-*.js`) ändern sich pro Build; relevant sind Grössenordnungen und gzip. ### 1.1 Einstieg & globale Vendor-Chunks (Auszug letzter Lauf CI-lokal) | Asset (Muster) | raw kB | gzip kB | Rolle | |----------------|--------|---------|--------| | `index.html` | 1.84 | 0.73 | Einstieg | | `index-*.css` | 127.55 | 21.58 | Globale Styles | | `index-*.js` (App-Shell / Router) | 64.83 | 17.45 | Haupteinstieg nach Code-Splitting | | `vendor-react-*.js` | 142.42 | 45.67 | React + DOM | | `vendor-router-*.js` | 65.94 | 22.51 | react-router | | `vendor-markdown-*.js` | 161.54 | 49.31 | Markdown-Stack (wird mit Routen geladen) | | `vendor-pdf-*.js` | 390.80 | 128.98 | jsPDF (Route-bezogen) | ### 1.2 Schwerste Route-Chunks (lazy, nach Route) | Bereich | typ. Chunk-Grösse (raw / gzip) | Datei-Muster (Beispiel) | |---------|-------------------------------|-------------------------| | Trainingsplanung | 71.81 kB / 18.67 kB | `TrainingPlanningPage-*.js` | | Übung bearbeiten | 91.31 kB / 22.49 kB | `ExerciseFormPage-*.js` | | Medienbibliothek | 59.42 kB / 13.69 kB | `MediaLibraryPage-*.js` | | Dashboard | 19.97 kB / 5.93 kB | `Dashboard-*.js` | **Abnahme Phase 0 (Bundle):** Zahlen dokumentiert; Re-Run: `npm run build` und Tabelle abgleichen. --- ## 2. API-Latenz (p95) – Top-Routen **Messung** erfolgt auf **Zielumgebung** (z. B. dev.shinkan / prod) mit gleicher Topologie wie Nutzer (HTTPS, Proxy). Nicht aus dem leeren Arbeitsverzeichnis ohne laufendes Backend messbar. ### 2.1 Vorgehen (empfohlen) - **Access-Logs** des Reverse-Proxy (Request-Zeit), oder - **APM** / OpenTelemetry, oder - **k6** mit authentifizierten Szenarien (Token aus Testaccount; Header `X-Auth-Token`, ggf. `X-Active-Club-Id`), oder - manuell: wiederholte `curl -w '%{time_total}\n'` mit gleichem Token ### 2.2 Vorlage (aus Umgebung ausfüllen) | Route (Beispiel) | Methode | p95 (ms) | Datum / Umgebung | Bemerkung | |------------------|---------|----------|------------------|-----------| | `/api/profiles/me` | GET | *—* | *nach Messung* | | | `/api/exercises` (Liste, typ. Query) | GET | *—* | *nach Messung* | | | `/api/training-units` (Liste, typ. Query) | GET | *—* | *nach Messung* | | | `/api/media-assets` (Liste) | GET | *—* | *nach Messung* | | | `/health` | GET | *—* | *nach Messung* | k6: siehe `scripts/load/` | **Abnahme Phase 0 (API):** Verfahren steht; Tabelle mindestens für **`/health`** nach erstem k6-Lauf befüllbar; übrige Zeilen bei nächstem Monitoring-Export. --- ## 3. Lasttestszenario ### 3.1 E2E-Smoke (fachlicher Pfad) - **Befehl:** Repository-Root, `npm run test:e2e` (setzt `PLAYWRIGHT_BASE_URL`, Testuser per Env, siehe `.gitea/workflows/test.yml`). - **Abdeckung:** Login, Dashboard, Navigation u. a. – entspricht grob „Login → Dashboard → weitere Screens“. - **Baseline notieren:** Dauer eines vollen Laufs, Anzahl passed (z. B. 26 Tests), Datum. | Messung | Wert | Datum | |---------|------|-------| | Playwright Gesamtlauf (lokal/CI) | *—* | *nach Messung* | | passed / total | 26 / 26 (Ziel) | | ### 3.2 EXPLAIN (Phase 2 – Lesepfade) - **Datei:** **`scripts/load/explain-readpaths.sql`** — repräsentative Statements für `list_exercises` / Stufenfilter / `training_units`; auf der Ziel-DB mit `EXPLAIN (ANALYZE, BUFFERS)` ausführen (Token/Tenant nicht im Skript; wie bei echten API-Queries filtern). ### 3.3 k6 – parallele /health - **Skript:** `scripts/load/k6-health-baseline.js` - **CI:** Läuft **automatisch** im Gitea-Workflow im Job **`k6-health-baseline`** (eigenständig, ohne Playwright; `.gitea/workflows/test.yml`). Parallel dazu **Playwright** im Job **`playwright-tests`**. - **Lokal:** siehe `scripts/load/README.md` - **Baseline notieren:** k6-Ausgabe `http_req_duration` p(95), Checks succeeded. | Szenario | p95 / Fehlerquote | Datum / BASE_URL | |----------|-------------------|------------------| | 10 VUs, 30 s `/health` | *—* | *nach Messung* | ### 3.4 Aus dem Deployment-/CI-Log übernehmen (k6 `k6-health-baseline`) Das Skript `scripts/load/k6-health-baseline.js` nutzt **10 VUs**, **30 s**, Ziel **`GET {BASE_URL}/health`** (siehe Workflow-Env für `BASE_URL`). **In die Tabelle oben (Abschnitt 3.3) eintragen — aus der k6-Zusammenfassung am Ende des Jobs:** | Feld in BASELINE_SNAPSHOT | Wo im k6-Log (typisch) | |---------------------------|-------------------------| | **p95** (Latenz ms) | Zeile **`http_req_duration`** → Wert **`p(95)=…`** (ganze Zahl oder ms mit Einheit wie `12.34ms`) | | **Fehlerquote** | Zeile **`http_req_failed`** → z. B. `0.00%` bzw. `✓ 0%` — oder kurz „0 %“ notieren | | **Checks** (optional) | Zeile **`checks`** → Anteil **`✓`** (soll **100 %** sein, sonst Hinweis) | | **Datum / BASE_URL** | Deploy-Datum + die **öffentliche** Basis-URL des Laufs (wie im Workflow gesetzt, z. B. `https://dev.shinkan.jinkendo.de`) | | **App-Version** (optional) | dieselbe wie im Deploy (`backend/version.py` / Release), damit M2-Vergleich ressortfähig bleibt | **Zusätzlich (Abschnitt 2.2):** nur die Zeile **`/health` GET`** mit dem **gleichen** p95 befüllen, wenn ihr dort noch Platzhalter habt — echte API-Routen (`/api/...`) kommen weiter aus Monitoring/k6 mit Auth, nicht aus diesem Job. --- ## 4. Nächster Schritt (Roadmap) - **Phase 0** ist für den Pipeline-Teil **abgeschlossen**: Bundle dokumentiert; **k6** läuft in CI nach jedem relevanten Deploy (mit Test-Suite); API-p95-Tabellen kann das Team aus Monitoring weiter befüllen (optional, kein Deploy-Blocker). - **Phase 2** (Backend Lesepfade) ist **abgeschlossen** — siehe [UMSETZUNGSPLAN_ROADMAP.md](./UMSETZUNGSPLAN_ROADMAP.md); nach Deploy **p95 erneut messen** und mit den Werten aus Abschnitt 2 dieser Datei vergleichen (**Meilenstein M2**). --- ## Verweise - Roadmap: [UMSETZUNGSPLAN_ROADMAP.md](./UMSETZUNGSPLAN_ROADMAP.md) - k6: [scripts/load/README.md](../../scripts/load/README.md)