[Prestaties][P1] Privacy- en layoutmemo's vallen boven 512 dia's volledig weg (0,4 → 386 ms per toetsaanslag) #2622

Closed
opened 2026-10-28 16:31:34 +00:00 by brenno · 1 comment
Owner

Symptoom

Boven een bepaalde decksgrootte wordt typen ineens veel trager — geen geleidelijke afname maar een klif.

Oorzaak

Meerdere memo's zijn een globale LRU met een vast plafond, terwijl ze per toetsaanslag sequentieel over alle dia's worden gelezen. Een sequentiële scan over meer items dan de capaciteit geeft bij LRU 100% misses: elk item wordt verdrongen vlak voordat het weer nodig is.

  • Tekst-privacyscan: _slideScanCache = LruCache(512) (lib/services/privacy/privacy_scan_memo.dart:35). Daarbij zit de dia-index in de sleutel, dus één dia bovenaan invoegen maakt ook alle volgende dia's ongeldig.
  • Render-layoutmemo: _renderLayoutCache = LruCache(512) (lib/services/slide_layout_metrics.dart:39), gedeeld door strook, preview, overzichtsraster, presentator (huidige + volgende) en beamer — elk op een eigen breedte. Een deck van 150 dia's op vier breedtes zit daar al boven.
  • Rich-text-plan: LruCache(256) (lib/services/rich_text_layout.dart:316).
  • Gezichtsscan: LruCache(256) — zie #2619.

Meting

Tijdelijke meetproef (debug-JIT, Apple Silicon), herhaalde memoizedDeckScan op een ongewijzigd deck (= wat één toetsaanslag kost):

Dia's Herhaalde scan
500 0,4 ms
520 386 ms
600 427 ms

Voorgestelde oplossing

  • Vervang deze globale LRU's door een Expando per Slide (zoals de kwaliteitscontrole al doet): de memo leeft precies zo lang als de dia, groeit nooit los van het geheugen dat het deck zelf al houdt, en kent geen klif. Waar meerdere breedtes nodig zijn: een klein mapje per dia (breedte → resultaat, max. 6).
  • Haal de index uit de sleutel van de privacyscan: scan de dia zonder index en zet de index pas bij het samenvoegen (de kwaliteitscontrole doet precies dit met reindexed).

Wat overeind moet blijven

Identieke uitkomst aan de ongememoiseerde scan — privacy_scan_memo_test.dart vergelijkt die al op willekeurige decks.

Toets

Schaaltoets: deck van 1000 dia's, tweede memoizedDeckScan < 5 ms; dia bovenaan invoegen → slechts één dia opnieuw gescand.

Onderdeel van de prestatie- en stabiliteitsinspectie van 28-10-2026 (EPIC #2637).

## Symptoom Boven een bepaalde decksgrootte wordt typen ineens veel trager — geen geleidelijke afname maar een klif. ## Oorzaak Meerdere memo's zijn een globale LRU met een vast plafond, terwijl ze per toetsaanslag **sequentieel over alle dia's** worden gelezen. Een sequentiële scan over meer items dan de capaciteit geeft bij LRU 100% misses: elk item wordt verdrongen vlak voordat het weer nodig is. - Tekst-privacyscan: `_slideScanCache = LruCache(512)` (`lib/services/privacy/privacy_scan_memo.dart:35`). Daarbij zit de dia-**index** in de sleutel, dus één dia bovenaan invoegen maakt ook alle volgende dia's ongeldig. - Render-layoutmemo: `_renderLayoutCache = LruCache(512)` (`lib/services/slide_layout_metrics.dart:39`), gedeeld door strook, preview, overzichtsraster, presentator (huidige + volgende) en beamer — elk op een eigen breedte. Een deck van 150 dia's op vier breedtes zit daar al boven. - Rich-text-plan: `LruCache(256)` (`lib/services/rich_text_layout.dart:316`). - Gezichtsscan: `LruCache(256)` — zie #2619. ## Meting Tijdelijke meetproef (debug-JIT, Apple Silicon), herhaalde `memoizedDeckScan` op een ongewijzigd deck (= wat één toetsaanslag kost): | Dia's | Herhaalde scan | |---|---| | 500 | 0,4 ms | | 520 | **386 ms** | | 600 | 427 ms | ## Voorgestelde oplossing - Vervang deze globale LRU's door een **`Expando` per `Slide`** (zoals de kwaliteitscontrole al doet): de memo leeft precies zo lang als de dia, groeit nooit los van het geheugen dat het deck zelf al houdt, en kent geen klif. Waar meerdere breedtes nodig zijn: een klein mapje per dia (breedte → resultaat, max. 6). - Haal de index uit de sleutel van de privacyscan: scan de dia zonder index en zet de index pas bij het samenvoegen (de kwaliteitscontrole doet precies dit met `reindexed`). ## Wat overeind moet blijven Identieke uitkomst aan de ongememoiseerde scan — `privacy_scan_memo_test.dart` vergelijkt die al op willekeurige decks. ## Toets Schaaltoets: deck van 1000 dia's, tweede `memoizedDeckScan` < 5 ms; dia bovenaan invoegen → slechts één dia opnieuw gescand. Onderdeel van de prestatie- en stabiliteitsinspectie van 28-10-2026 (EPIC #2637).
Author
Owner

Opgepakt. Tak: fix/prestatie-2635-2621-2622-2625. Verwachte reikwijdte: lib/services/privacy/privacy_scan_memo.dart, lib/services/slide_layout_metrics.dart, lib/services/rich_text_layout.dart en de schaaltoets. Gezichtsscan (#2619) blijft buiten deze tak.

Opgepakt. Tak: fix/prestatie-2635-2621-2622-2625. Verwachte reikwijdte: lib/services/privacy/privacy_scan_memo.dart, lib/services/slide_layout_metrics.dart, lib/services/rich_text_layout.dart en de schaaltoets. Gezichtsscan (#2619) blijft buiten deze tak.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
LibreKAT/Ocideck#2622
No description provided.