Files
imajviewer/docs/rapor-pan-kilitleme-nuks.md
T

200 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Rapor — Efekt Uygulanmış Görselde Pan Sırasında Kilitlenme (Nüks)
Tarih: 2026-08-06
Durum: Analiz — hipotezler hazır, açık sorular kullanıcı yanıtını bekliyor
## 1. Semptom (yeni bildirim)
- Donma sorunu **yeniden ortaya çıktı** — bu kez **"diğer bilgisayarda"** (VM değilse
ortamı bilinmiyor; önceki testler Xubuntu VM + llvmpipe idi).
- Tetikleyici farklı: önceki nüksler **efekt sürüklemesi sırasında** idi
(contrast/saturation/brightness/rotate drag). Şimdi **efekt uygulanmış durumda
(değerler sabit) iken PAN yaparken** kilitlenme.
- "Olmadık zamanlarda" — rastgele zamanlarda, her pan'da değil.
## 2. Önceki Teşhisler ve Çözümler (kayıt özeti)
| Tarih | Teşhis | Çözüm | Durum |
|---|---|---|---|
| 03 Ağu | **Kuyruk birikmesi**: pointer event hızı (100-250/sn) > llvmpipe kare hızı → setState her event'te → UI thread %100, 30-60sn donma | `_markRenderDirty()` frame-throttle (kare başına max 1 rebuild) + `ResizeImage` (viewport×2) + provider memoize + cache 16/256MB + galeri geçişinde `imageCache.clear()` | Uygulandı, ölçüldü (raster ort ~15ms, max ~50ms, kuyruk birikmesi yok) |
| 06 Ağu | **İlk kullanım shader derlemesi (B1)**: process başına soğuk Skia/GL cache; ilk ColorFiltered/Transform kullanımı 15sn-1dk derleme | **Shader warmup**: açılışta gizli Opacity(0) katmanla filtre + rotate shader'larını derlet | Uygulandı (release build + kurulum 06 Ağu) |
## 2b. Kullanıcı Yanıtları (2026-08-06, ikinci bildirim)
- Ortam: **gerçek makine** — `Mesa Intel(R) HD Graphics 3000 (SNB GT2)` (Sandy
Bridge iGPU, 2011). mesa i965 driver GLSL'i **LLVM ile CPU'da derler** → karmaşık
shader varyantları 30sn'ye çıkabilir. 12GB RAM, son sürüm kurulu.
- Test sonuçları (kullanıcı):
- **Resim büyükse (dosya ~1MB+) oluyor**; küçük görselde olmuyor.
- **Fill modda olmuyor, fit modda oluyor.**
- **İlk açılışta fit moda geçip rotate edilirse oluyor** — tek seferlik, sonra
tekrar değil (kullanıcı "sanırım" ile ifade etti, teyit beklenecek).
- Bu bilgiler **Aday F'yi doğruluyor**: warmup 1x1 gizli katmanda yapılıyor, gerçek
kullanımın (büyük doku + fit BoxFit.contain + rotate + ColorFiltered) shader
varyantı warmup'ta derlenmiyor → ilk gerçek kullanımda 30sn derleme.
- Aday A (ColorFiltered CPU filtrelemesi) ve C (bellek) elendi — GPU var, RAM bol.
- **EKLENTİ (kullanıcı kurcalayınca):** Fill modda da oluyor; **"biraz zorlayınca
aynı resimde tekrar oldu"** — yani tek seferlik DEĞİL. Bu Aday F'yi (ilk kullanım
derlemesi, cache'li kalır) **zayıflatıyor**; varyant sayısı fazlaysa her yeni
kombinasyon yeni derleme olabilir (aşağıda Aday H/I).
Her iki çözüm de mevcut kodda aktif: `image_canvas.dart` → `_markRenderDirty`,
provider memoize (`_cachedProvider`), `_buildWarmupLayer()`.
## 3. Yeni Analiz — Neden "Efekt + Pan" Kilitlenir?
Pan akışı: `_onPanUpdate` → `_tx/_ty += delta` → `_clamp()` → `_markRenderDirty()`.
### Aday A — ColorFiltered her pan frame'inde tüm görseli CPU'da filtreliyor ⭐
- Efekt aktifken (`hasFilter == true`) her rebuild'te `ColorFiltered` → `Image` tüm
görsel 5x4 matrisle filtrelenir. Pan'da translate değişir → her frame'de yeniden
boyama + filtreleme.
- 4000×3000 görsel ≈ 12M piksel; llvmpipe'ta filtre + ölçekleme + translate ≈
20-60ms/kare. FPS 15-50'ye düşer → **"takılma" hissi**.
- `_markRenderDirty` kuyruk birikmesini engeller ama kare başına maliyet yüksekse
düşük FPS kalıcı olur. Büyük görsel + zayıf makinede bu "kilitlenme" gibi algılanabilir.
- **Rotate aktifse** (pan serbest, `_clamp` erken return) Transform + ColorFiltered
birlikte — en ağır kombinasyon.
### Aday B — `_clamp()` pan event hızında `findRenderObject()` çağırıyor ⭐
- `_onPanUpdate` her event'te `_clamp()` çağırır; fit modda `_clamp()` içinde
`_imageKey.currentContext?.findRenderObject()` (satır 77) **pointer hızında**
(throttle'ın DIŞINDA) render tree sorgusu yapar. Pan event'leri 100-250/sn →
gereksiz layout/tree traversal yükü. Kilitlenme üretmez ama takılmayı artırır.
### Aday C — Bellek/GC baskısı ("olmadık zamanlarda" rastgeleliğin en iyi adayı)
- Rastgele kilitlenme imzası GC/swap'e işaret eder. "Diğer bilgisayar"da RAM azsa
(8GB altı) veya başka işler varsa: büyük görsel decode + 256MB cache + pan sırasında
GC pause → kısa ama algılanabilir donmalar.
- Pan sırasında yeni decode yok (memoize) → cache baskısı düşük; ama makine belleği
dar ise OS seviyesinde swap thrashing olabilir.
### Aday D — Eski binary / farklı ortam ("diğer bilgisayar")
- "Diğer bilgisayarda" kurulu sürüm bilinmiyor. Eski .deb (warmup/memoize öncesi)
kuruluysa sorun zaten açıklanır. Ayrıca o makinede donanım GPU'su VARSA teşhis
tamamen değişir (llvmpipe değil) — ColorFiltered donanımda ucuzdur, o zaman aday
C veya farklı bir sebep aranır.
### Aday E — Pan sırasında yeni frame kuyruğu (zayıf)
- `scheduleFrameCallback` kare başına 1 callback garanti eder; kare süresi uzarsa FPS
düşer ama kuyruk birikmez (03 Ağu ölçümü). Kilitlenme üretmez.
### Aday F — Warmup varyant eksikliği: 1x1 katman gerçek kullanımı derlemiyor ⭐⭐⭐
- Warmup (`_buildWarmupLayer`) **1x1 boyutunda** gizli katmanla filtre + rotate
shader'larını derletiyor. Skia/GL'de shader varyantları **doku boyutu, sampling
modu, filtre kalitesi** gibi parametrelere göre ayrı derlenir.
- Gerçek kullanımda **büyük görsel** (4000x3000) + `FilterQuality.high` +
`BoxFit.cover/contain` + `ColorFiltered` + pan/zoom `Transform` — bu kombinasyonun
shader'ı 1x1 warmup'ta derlenenle **aynı varyant olmayabilir** → ilk gerçek
kullanımda derleme yine olur → 30sn kilitlenme.
- "Efekt uygulanmışken pan yaparken" tetikleyicisi: pan/zoom + ColorFiltered birlikte
ilk kez kullanıldığında varyant derlenir; sonrası cache'li → "olmadık zamanlarda"
ve "her pan'da değil" imzası birebir uyuyor.
- GPU'da shader derleme süresi genelde ms seviyesindedir; **zayıf/iç ekran kartı +
mesa/LLVM backend** ile 30sn'ye çıkabilir. "İyi kötü ekran kartı" ifadesi bu
olasılığı güçlendiriyor.
- **Warmup'ın gerçek boyutla yapılması gerekir**: gizli katman 1x1 yerine mevcut
görselin boyutunda (veya viewport boyutunda) olmalı; ayrıca pan/zoom Transform'u
da warmup'a dahil edilmeli.
### Aday G — Gerçek GPU driver / doku sınırı
- Zayıf GPU'da büyük doku (12MP RGBA ≈ 48MB) + ColorFiltered → driver'da aşırı
yavaş path veya GL sync beklemesi. `glxinfo -B` renderer string'i kritik
(NVIDIA nouveau / AMD radeon / Intel / llvmpipe?).
### Aday H — Skia varyant cache dolması / her kombinasyon yeni derleme ⭐⭐
- "Aynı resimde tekrar oldu" → tek seferlik derleme değil. Skia'da her farklı
kombinasyon (zoom seviyesi × rotate açısı × efekt değeri × fit/fill × filtre
kalitesi) farklı shader varyantı üretebilir; varyant cache'i sınırlıysa (LRU)
eski varyant atılır → aynı kombinasyon tekrar kullanılınca YENİDEN derlenir →
30sn. "Zorlayınca" = çok varyant üretmek = cache'i doldurmak = tekrar derleme.
- Bu, "ilk kullanımda" + "sonra tekrar" imzasını birlikte açıklayan hipotez.
### Aday I — Intel HD 3000 GL sync / doku upload darboğazı ⭐⭐
- Sandy Bridge iGPU paylaşımlı bellek kullanır; büyük doku upload + ColorFiltered
+ Transform her frame'de GL sync bekleyebilir. `_markRenderDirty` throttle frame
üretimini sınırlar ama **raster thread** yavaş kalırsa UI thread frame kuyruğunu
tüketemez → 30sn'lik görünür donma (olaylar işlenir, görsel gecikir — önceki
raporlardaki imza).
- Doku boyutuna duyarlılık (1MB+ görsel) + fill/fit farkı (BoxFit.cover kırpar →
daha küçük etkin doku; contain → tam doku işlenir) bu hipotezle uyumlu.
- Intel HD 3000'de `LIBGL_ALWAYS_SOFTWARE=1` (llvmpipe) ile karşılaştırma testi
ayırt edici: GL sync sorunu ise software'de farklı davranır.
## 4. Hipotez Önceliklendirme
| Aday | Açıkladığı | Gücü |
|---|---|---|
| A (ColorFiltered her frame) | Efekt+pan takılması, "kilitlenme" hissi | ⭐⭐ (efekt açıkken kaçınılmaz maliyet; azaltılabilir) |
| B (`_clamp` findRenderObject) | Ek pan yükü | ⭐ (kolay düzeltilir) |
| C (bellek/GC) | "Olmadık zamanlarda" rastgelelik | ⭐⭐ (makine belleği bilinmiyor) |
| D (ortam/eski binary) | Tamamen farklı kök | ⭐ (önce doğrulanmalı) |
## 5. Önerilen Çözüm Yolları (rapor onayı sonrası)
### Seçenek 1 — Pan sırasında filtre maliyetini azalt (Aday A)
- Efekt aktifken pan/zoom sırasında `FilterQuality.high` → `FilterQuality.medium`
(görsel kalite farkı minimal, llvmpipe yükü düşer) — tek satır.
- Pan sırasında `cacheWidth`'i düşürme (memoize zaten sabit tutuyor) — gerek yok.
- **Alternatif:** pan sırasında geçici düşük çözünürlük önizlemesi (mevcut görseli
küçük boyutta filtrele) — karmaşık, önce basit yol denenir.
### Seçenek 2 — `_clamp()` içindeki `findRenderObject` yükünü azalt (Aday B)
- `_imageKey.currentContext?.findRenderObject()` yalnızca fit modunda lazım; pan'da
`_vpSize` değişmediği sürece tekrar sorgulamaya gerek yok — `_clamp`'in render
sorgusunu her pan event'inde değil, sadece layout değişince yap. (Dikkatli:
rotate varken `_clamp` zaten erken return ediyor; fit modunda kilitlenme riski yok.)
### Seçenek 3 — Ortam doğrulaması (Aday D) — rapor öncesi şart
- "Diğer bilgisayar"da: `glxinfo -B | grep -i renderer` (llvmpipe mi GPU mu),
`free -h`, kurulu sürüm (`.deb` tarihi / `imajviewer --version` yoksa binary
timestamp). Ayrıca aynı görselle **bu VM'de** tekrar dener misin — nüks VM'de
de mi, sadece diğer makinede mi?
## 6. Kalan Açık Sorular
1. "Diğer bilgisayar" hangisi — başka VM mi, gerçek makine mi? Donanım GPU'su var mı
(`glxinfo -B` çıktısı)?
2. O makinede kurulu sürüm: son `.deb` (2026-08-06 sonrası) mi, yoksa eski mi?
3. Kilitlenme süresi ne kadar — 1-2sn mi, 10sn+ mı, yoksa "kapatmak zorunda kaldım" mı?
4. Hangi efekt uygulanmışken pan yapıyorsun — contrast mi, rotate mi (rotate en ağırı)?
5. Görsel boyutu ne — büyük fotoğraf mı (4000px+), küçük ekran görüntüsü mü?
6. Aynı görselle bu VM'de (llvmpipe) pan dener misin — nüks VM'de de oluyor mu?
## 7. Ölçüm Planı (onaylanırsa)
Skill'deki `references/llvmpipe-perf-measurement.md` akışı: geçici
`addTimingsCallback` (FRAME build/raster süreleri) + `pidstat` CPU. Ölçüm sırasında
kullanıcı elle pan yapar ("sen aç ben yaparım"). Enstrümantasyon geçicidir ve
sonrası temizlenir. VM'de ölçüm yapılabilir; "diğer bilgisayar"da enstrümantasyonlu
build kurmak gerekir (kullanıcı onayı şart).
## 8. Sonuç
İki önceki çözüm (throttle + warmup) doğru teşhislere dayanıyordu ve ilk iki donma
imzasını çözdü. Yeni imza **farklı**: efekt SABİT iken pan. En güçlü açıklama
Aday A (ColorFiltered'in her pan frame'inde tam görseli CPU'da filtrelemesi) —
özellikle büyük görsel + zayıf makinede "kilitlenme" hissi yaratır. Rastgelelik için
Aday C (bellek/GC) ve Aday D (ortam) doğrulanmalı. Kullanıcı yanıtları gelince
rapor güncellenir ve çözüm yolları netleşir.
## 9. Kapanış Notu (2026-08-06)
Kullanıcı donma sırasında `top -b -d 1` ölçümü başlattıktan sonra **nüks olmadı**
(ne denediyse kilitlenme/takılma görülmedi). Nüks koşulları belirsiz; konu bu
raporla **askıda bırakıldı** — kullanıcı talep ederse yeniden açılır. Olası ipucu:
ölçüm sırasında sistem yükü değişince davranış değişti (Aday I — GL sync/GPU yükü
ile ilişkili olabilir; kesin teşhis yapılmadı).