[Prestaties][P0] Split-run-index meet bij elke toetsaanslag alle runleden opnieuw (136–535 ms per toets) #2620

Closed
opened 2026-10-28 16:31:32 +00:00 by brenno · 0 comments
Owner

Symptoom

In een grote presentatie met lange, over meerdere dia's verdeelde lijsten ("Splits slide", of geïmporteerde PowerPoint-decks) wordt typen merkbaar traag — ook als je in een dia typt die niets met die reeksen te maken heeft.

Oorzaak

splitRunLayoutIndex (lib/services/split_run.dart:190) cachet de index in een Expando op de dialijst (regel 196). Elke bewerking levert via deck.copyWith(slides: …) een nieuwe lijst, dus na elke toetsaanslag mist de cache en bouwt buildSplitRunLayoutIndex (regel 226) de hele index opnieuw — inclusief een volledige TextPainter-inpassing (splitRunMemberScale) van elk lid van elke reeks. De eerste diaminiatuur die daarna bouwt betaalt dat (lib/widgets/panels/slide_list_panel.dart:534), en preview, overzicht en presentator lezen dezelfde index.

#1051 maakte de index per deckrevisie; dat lost herhaling bínnen één revisie op, maar niet tussen twee toetsaanslagen. De kwaliteitscontrole memoiseert exact dezelfde meting wél per dia (_memoizedRunScale, lib/services/slide_quality/slide_quality_analyzer_density.dart:561), de index niet.

Meting

Tijdelijke meetproef (debug-JIT, Apple Silicon), één herbouw met een nieuwe lijst — dus precies wat één toetsaanslag kost:

Reeksen × pagina's Runleden Herbouw per toetsaanslag
10 × 5 50 136 ms
40 × 5 200 535 ms

Lineair in het aantal runleden, maar dat aantal wordt per toetsaanslag volledig betaald.

Voorgestelde oplossing

Memoiseer de per-lid-meting per dia (immutable, identiteit) in plaats van per lijst: één gedeelde Expando<Slide> met sleutel (profiel-identiteit, font, diaverhouding), gebruikt door zowel buildSplitRunLayoutIndex als de kwaliteitscontrole (één functie, bv. memoizedSplitRunMemberScale). Na een toetsaanslag wordt dan alleen de gewijzigde dia opnieuw gemeten; de rest van de index is een goedkope lineaire gang.

Wat overeind moet blijven

Dezelfde gedeelde schaal per reeks op alle oppervlakken (strook, preview, presentator, beamer, export) — de bestaande tests in test/shared_split_fit_scale_test.dart blijven groen.

Toets

Uitbreiding van test/shared_split_fit_scale_test.dart: reeks van 150 pagina's, vervang één dia (nieuwe lijst) → measureMember wordt één keer aangeroepen, niet 150 keer.

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

## Symptoom In een grote presentatie met lange, over meerdere dia's verdeelde lijsten ("Splits slide", of geïmporteerde PowerPoint-decks) wordt typen merkbaar traag — ook als je in een dia typt die niets met die reeksen te maken heeft. ## Oorzaak `splitRunLayoutIndex` (`lib/services/split_run.dart:190`) cachet de index in een `Expando` op de **dialijst** (regel 196). Elke bewerking levert via `deck.copyWith(slides: …)` een nieuwe lijst, dus na elke toetsaanslag mist de cache en bouwt `buildSplitRunLayoutIndex` (regel 226) de hele index opnieuw — inclusief een volledige TextPainter-inpassing (`splitRunMemberScale`) van **elk lid van elke reeks**. De eerste diaminiatuur die daarna bouwt betaalt dat (`lib/widgets/panels/slide_list_panel.dart:534`), en preview, overzicht en presentator lezen dezelfde index. #1051 maakte de index per deckrevisie; dat lost herhaling bínnen één revisie op, maar niet tussen twee toetsaanslagen. De kwaliteitscontrole memoiseert exact dezelfde meting wél per dia (`_memoizedRunScale`, `lib/services/slide_quality/slide_quality_analyzer_density.dart:561`), de index niet. ## Meting Tijdelijke meetproef (debug-JIT, Apple Silicon), één herbouw met een nieuwe lijst — dus precies wat één toetsaanslag kost: | Reeksen × pagina's | Runleden | Herbouw per toetsaanslag | |---|---|---| | 10 × 5 | 50 | **136 ms** | | 40 × 5 | 200 | **535 ms** | Lineair in het aantal runleden, maar dat aantal wordt per toetsaanslag volledig betaald. ## Voorgestelde oplossing Memoiseer de per-lid-meting per **dia** (immutable, identiteit) in plaats van per lijst: één gedeelde `Expando<Slide>` met sleutel (profiel-identiteit, font, diaverhouding), gebruikt door zowel `buildSplitRunLayoutIndex` als de kwaliteitscontrole (één functie, bv. `memoizedSplitRunMemberScale`). Na een toetsaanslag wordt dan alleen de gewijzigde dia opnieuw gemeten; de rest van de index is een goedkope lineaire gang. ## Wat overeind moet blijven Dezelfde gedeelde schaal per reeks op alle oppervlakken (strook, preview, presentator, beamer, export) — de bestaande tests in `test/shared_split_fit_scale_test.dart` blijven groen. ## Toets Uitbreiding van `test/shared_split_fit_scale_test.dart`: reeks van 150 pagina's, vervang één dia (nieuwe lijst) → `measureMember` wordt **één** keer aangeroepen, niet 150 keer. Onderdeel van de prestatie- en stabiliteitsinspectie van 28-10-2026 (EPIC #2637).
brenno 2026-10-29 12:19:35 +00:00
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#2620
No description provided.