3.9 KiB
#86 — Optimisation globale des performances (phase 3)
Statut : ✅ livré | Zone : backend (
indexer.py,mutations.py) Prérequis déjà livrés : BUG-033 (recherche via inverted index), BUG-040 (PDF lazy), BUG-025 (caps regex).
Contexte
La roadmap #86 demandait : recherche simple + tool IA via l'inverted index, indexation incrémentale + scan différentiel au démarrage, extraction PDF/excalidraw différée et caps CPU sur les opérations regex. Trois de ces cinq points étaient déjà couverts par des correctifs antérieurs ; cette livraison ferme les deux points restants.
Ce qui était déjà livré (rappel)
| Point #86 | Livré par | État |
|---|---|---|
Recherche simple + search_fulltext via inverted index |
BUG-033 | search() récupère ses candidats via l'inverted index (intersection + expansion de préfixes), repli scan pendant la construction |
| Extraction PDF différée | BUG-040 | _scan_vault ne lit que les métadonnées ; enrich_pdf_texts() extrait après index |
| Caps CPU regex | BUG-025 | validate_regex (longueur ≤ 500, rejet quantificateurs imbriqués), contenu tronqué à 200 kio, matchs plafonnés à 1 000 |
Livré ici
1. Scan différentiel au démarrage (backend/indexer.py)
_scan_vault(..., previous_files): quand un snapshot{relative_path: file_info}est fourni, toute entrée dontsizeetmodifiedsont inchangés est réutilisée sans lecture disque ni re-parse (copie du dict, tags recomptés, wikilinks ré-enregistrés depuis le contenu caché pour reconstruire l'index de backlinks).build_index()capture le snapshot précédent avant leclear()et le transmet à chaque scan de vault (viafunctools.partialpour l'executor) ;reload_single_vault()fait de même pour son vault. Seuls leos.walk+stat(bon marché) tournent à chaque passe ; le retour inclutreused(hits différentiels, loggé par vault).- Premier démarrage (aucun snapshot) : comportement identique à avant.
2. Extraction excalidraw différée (backend/indexer.py)
- Le scan ne lit plus les
.excalidraw/.excalidraw.md: titre dérivé du nom de fichier,contentvide, flagexcalidraw_text_pending(plus de décompression lz-string pendant le scan). enrich_pdf_texts()traite désormais les deux flags (pdf+excalidraw) via_read_excalidraw_indexable_text()exécuté dans l'executor, avec notification du hook d'index incrémental comme pour les PDF. Nom conservé pour compatibilité (tests,main.py,reload_index,reload_single_vaultinchangés côté appel).- Le chemin incrémental fichier-à-fichier (
_index_single_file_sync, watcher) reste immédiat : un seul fichier ne justifie pas le différé.
3. Garde-fou taille sur replace_in_files (backend/services/mutations.py)
- Nouvelle constante
MAX_REPLACE_FILE_BYTES(5 Mio) : tout fichier dépassant le plafond est sauté (warning loggé) au lieu d'être lu intégralement puis balayé par le pattern utilisateur. Complète les caps BUG-025 (qui couvrent la recherche, pas le remplacement qui opère sur le contenu disque complet par nature).
Tests
tests/test_perf_phase3.py (9 tests) : différé excalidraw au scan (.excalidraw +
.excalidraw.md), remplissage par l'enrichissement, reused == 0 au premier scan,
réutilisation à l'identique, re-parse du fichier modifié, ajout/suppression, skip
replace sur fichier surdimensionné + cas passant nominal.
Limites connues
- Pas de persistance disque de l'index : le différentiel joue sur les rebuilds dans le
même processus (
reload_index,reload_single_vault), pas entre deux redémarrages (persistance = #85, phase 2). - La comparaison
size + mtimene détecte pas une modification qui conserverait taille et mtime à la milliseconde près (cas pathologique, le watcher temps réel couvre les modifications en cours d'exécution).