# Panel Performans Çalışması (2026-08-18)

"Yeni harita açınca / sayfayı yenileyince çok uzun bekliyorum" şikâyetinin kök neden
analizi ve uygulanan çözümler.

## Ölçülen tablo (lokal, Windows + artisan serve)

| Senaryo | Önce | Sonra |
|---|---|---|
| Yeni harita (tam soğuk) TTFB | ~19,9 sn | ~5,8 sn (bir doğum tarihi için ömründe 1 kez) |
| Aynı doğum verisi, ev sistemi değişimi (build) | tam yeniden hesap (~6 sn) | ~1,5 sn |
| Yenileme (sıcak) TTFB | 760-1100 ms | ~340 ms |
| Yenileme (sıcak) DOMContentLoaded | 2,3-2,8 sn | ~0,8-1,2 sn |
| Yükleme overlay'inin kalkışı | 4-5 sn+ (min 850 ms taban) | ~3 sn (min 150 ms taban) |
| HTML boyutu | 11,2 MB | ~5,7 MB |
| swetest süreç fırtınası | her build'de 474 process | doğum tarihi başına 1 kez (30 gün cache) |

## Kök nedenler

1. **OPcache tamamen kapalıydı** (php.ini'de yorum satırı). Her istek tüm framework'ü
   ve 664 KB'lık panel Blade'ini sıfırdan derliyordu. → En büyük tekil etken.
2. Tek natal hesabı **474 ayrı swetest.exe** başlatıyordu (191 genişletilmiş asteroid +
   277 sabit yıldız, her biri ayrı process, üstelik string `proc_open` yüzünden her
   biri cmd.exe sarmalayıcısıyla). Bu konum/ev sisteminden bağımsız (geosentrik) veriler
   her ev sistemi değişiminde yeniden hesaplanıyordu.
3. SVG'ler hem DOM'a hem `window.CHARTS` JSON'una **çift** gömülüyordu (~3,5 MB israf);
   Blade girintileri yüzünden SVG'nin %40'ı, tab HTML'inin %67'si boşluktu.
4. HTML output cache yalnızca **5 dk TTL** idi; her 5 dakikada bir ~1 sn'lik tam Blade
   render tekrarlanıyordu.
5. Yükleme overlay'i **2,17 MB'lık GIF** kullanıyor ve her şey hazır olsa bile
   **850 ms** sabit bekletiyordu.

## Yapılan değişiklikler

### PHP yapılandırması (php.ini — LOKALDE yapıldı, PROD'DA DA YAPILMALI, aşağıya bak)
- `zend_extension=opcache`, `opcache.enable=1`, `opcache.enable_cli=1`
- `opcache.memory_consumption=256`, `opcache.interned_strings_buffer=32`,
  `opcache.max_accelerated_files=20000`
- `opcache.jit=tracing`, `opcache.jit_buffer_size=128M`
- `memory_limit = 512M`

### Backend
- `SwetestService::runGeocentricCachedSets()` (YENİ): sabit yıldız + genişletilmiş
  asteroid/yıldız komut grupları **tarih bazlı, 30 günlük** cache'e alındı — konum ve
  ev sisteminden bağımsız oldukları için. 474 process fırtınası artık doğum anı başına
  1 kez yaşanır (`swetest:geo:v2:*`).
- `runSweParallel`: string+cmd.exe yerine **array + bypass_shell** `proc_open`
  (süreç sayısı yarıya iner) + **64'lük havuz** sınırı. Çıktı satırları komut sırasına
  göre birleştirilir (parseOutput 'order' alanı korunur).
- Ana swetest cache TTL: 2 saat → **7 gün** (pozisyonlar deterministik).
- `ChartVisualizerService::minifySvg()` (YENİ): SVG/tab HTML çıktısındaki whitespace
  tek boşluğa indirgenir. `renderSvgForChartKey`, `chartPayload`, `loadChartLazy`,
  `chartCombo`, `compareRender*` ve `generateChartTabs` çıktılarına uygulanır.
- Panel HTML cache TTL: 5 dk → **60 dk** (`panel_html:v8`); tab cache `panel_tabs:v3`.

### Frontend (panel.blade.php)
- Ana harita + 4 mini kartın SVG'si artık CHARTS JSON'una gömülmüyor
  (`$domRenderedSvgKeys`); inline `hydrateChartSvgsFromDom()` DOM'daki kopyayı
  CHARTS'a taşıyor (aynı desen `swapThumbWithMain`'de zaten vardı). Davranış birebir.
- Yükleme overlay'i: `minVisibleMs` 850 → 150 (yapay bekletme kaldırıldı).
  Not: GIF önce CSS spinner ile değiştirilmişti, kullanıcı isteğiyle GERİ ALINDI —
  `firstSlider.gif` (2,17 MB) kullanılmaya devam ediyor; tarayıcı ilk yüklemeden
  sonra cache'lediği için tekrarlayan maliyeti düşük.
- Cross-origin CSS host'ları için `preconnect` (fonts.googleapis, unpkg, cdnjs, jsdelivr).

## PROD sunucusunda yapılması gerekenler (Windows)

1. Prod'un kullandığı `php.ini`'yi bul: `php --ini`
2. Şunları uygula (üstteki "PHP yapılandırması" bloğu):
   `zend_extension=opcache`, `opcache.enable=1`, `opcache.enable_cli=1`,
   `opcache.jit=tracing`, `opcache.jit_buffer_size=128M`, `memory_limit=512M`
3. PHP sürecini/web sunucusunu yeniden başlat (artisan serve ise process'i yeniden başlat).
4. Doğrulama: `php -r "var_dump(ini_get('opcache.enable'));"` → `"1"` olmalı.
5. Deploy sonrası (`gitpull-reload.bat` zaten `view:cache`/`config:cache` çalıştırıyor)
   ilk panel isteği cache'leri ısıtır.

Not: `opcache.validate_timestamps` default açık (2 sn) — `git pull` sonrası kod
değişiklikleri otomatik algılanır, ekstra bir şey gerekmez.

## 2. Tur (aynı gün, prod ölçümleri sonrası)

Prod'da `load-chart-lazy` 34 sn ölçüldü (lazy-build 11 + lazy-payload 22,5).
Yapılanlar:

- `load-chart-lazy`'ye `Server-Timing` (lazy-build / lazy-payload) eklendi.
- Batch'te tab HTML'i yalnızca aktif tip için üretilir (~100 → ~20 Blade render).
- Görünmeyen `*_transit` varyantlarının SVG'si lazy (10 → 6 SVG render).
- Hazır JSON cevabı 60 dk cache'lenir (`lazy_resp:v1`) — tekrar açılış ~0,3 sn.
- `_token` cache anahtarından çıkarıldı; lazy veri TTL 15 → 60 dk.
- SVG render cache (`svg_render:v1`, 7 gün, içerik-hash + şablon mtime) —
  `renderSvgForChartKey` üzerinden tüm SVG üretim noktaları.
- **Progressive yükleme:** overlay artık arka plan `load-chart-lazy` isteklerini
  ve eksik yan kartları BEKLEMEZ (panel.js `applySavedPanelLayout` arka plan
  görevi + panel.blade `miniReady` kuralı). Eksik slotlar iskeletle açılır,
  gelince dolar. HTML cache `panel_html:v10`.
- Regresyon düzeltmesi: erken bootstrap, init'teki programatik senkronların
  layout kaydı tetiklemesine yol açıyordu (HTML cache'i her yüklemede kırıyordu)
  → layout kaydı ilk kullanıcı etkileşimine kadar kilitli (`panelLayoutSaveArmed`).
- **Kayıtta ön-ısıtma:** `MyChartsController::store` cevap gönderildikten sonra
  (afterResponse) yeni doğum anının swetest fırtınasını arka planda çalıştırıp
  30 günlük geo-cache'i doldurur — kullanıcı haritayı açtığında hazırdır.
