---
from: qwen
to: dom
date: 2026-06-05T19:45:00+02:00
topic: perf-mvp-p1-diagnostic
status: delivered
priority: blocker
references:
  - decision: docs/coordination/decisions/2026-06-05_dom_d19-performance-mvp-p1.md
  - mission: docs/coordination/inbox/for-qwen/2026-06-05_19-30_dom-via-codex_perf-mvp-p1.md
---

# Performance MVP P1 - diagnostic Qwen

## Verdict court

Le retour Dom est coherent avec le code actuel : l'EXE Windows peut tomber en
traitement lourd mono-coeur pendant la rasterisation PDF. Sur une machine a 8
threads logiques, un seul coeur occupe donne environ 12,5 % CPU, ce qui colle
au symptome observe (~12 %).

La RAM a ~16 Go est plausible quand le document declenche docTR/OCR et la
rasterisation : modele OCR profond, images A4 300 dpi, tensors/numpy/PIL et
modele NER resident. Ce niveau est trop eleve pour un MVP exploitable.

Conclusion : performance bloquante avant diffusion. Hotfix MVP recommande
avant v11.5, sans toucher a `app_aivanov`.

## Points responsables identifies

1. Rasterisation page-level parallele desactivee en EXE PyInstaller.

- `anonymizer_core_refactored_onnx.py:22` importe `ProcessPoolExecutor`.
- `anonymizer_core_refactored_onnx.py:4277-4323` prepare une rasterisation
  parallele, mais `:4316-4319` force le mode sequentiel si `sys.frozen`.
- Commentaire code : en frozen, `ProcessPoolExecutor` relance l'EXE et ouvre
  des fenetres GUI fantomes. Le contournement actuel evite le bug UI mais
  sacrifie le multi-coeur.
- Impact : chaque page raster est rendue l'une apres l'autre dans `_rasterize_page`
  (`:4112-4175`), avec rendu PyMuPDF + PIL + JPEG/PNG.

2. La GUI force la sortie raster pour chaque document.

- `Pseudonymisation_Gui_V5.py:756-760` annonce "Sortie PDF Image (raster) -
  securite maximale".
- `Pseudonymisation_Gui_V5.py:1712-1717` appelle le moteur avec
  `make_vector_redaction=False` et `also_make_raster_burn=True`.
- `anonymizer_core_refactored_onnx.py:5020-5025` genere alors toujours
  `*.redacted_raster.pdf`.
- Impact : meme un PDF texte natif paye le cout de rendu image de toutes les
  pages. Ce choix est securise, mais trop couteux si la phase reste mono-coeur.

3. OCR docTR tres couteux sur pages pauvres en texte.

- `anonymizer_core_refactored_onnx.py:60-65` charge docTR si disponible.
- `:1096-1104` cree un modele `db_resnet50` + `crnn_vgg16_bn`.
- `:1250-1264` OCRise chaque page avec moins de 150 caracteres en image
  `get_pixmap(dpi=300)`.
- Une page A4 300 dpi represente environ 25 Mo en RGB brut, avant copies PIL,
  numpy et tensors. Sur un PDF scanne multi-pages, toutes les pages deviennent
  candidates OCR.
- Impact : forte RAM, temps long, et CPU potentiellement mal exploite selon
  PyTorch/docTR.

4. Les timings actuels ne suffisent pas pour isoler le goulet chez Dom.

- Le log Windows est bien a cote de l'EXE (`launcher.py:291-306`).
- Le moteur loggue certains evenements comme `OCR docTR : x/y pages remplacees`
  (`anonymizer_core_refactored_onnx.py:1280-1282`), mais pas les durees par
  etape ni le RSS peak.
- Sans instrumentation, on ne sait pas si le PDF de Dom bloque surtout sur
  extraction, OCR, NER, raster ou ecriture finale.

5. VLM/Ollama n'est pas la cause probable en beta non-admin.

- `Pseudonymisation_Gui_V5.py:80-90` neutralise `VlmManager` hors mode admin.
- `:765-781` n'affiche la checkbox VLM que si le manager existe.
- Donc la lenteur signalee ne doit pas etre attribuee au VLM sauf lancement
  admin explicite.

## Correctifs recommandes par ordre de risque

### Hotfix MVP faible risque

1. Ajouter des timings par etape dans `process_pdf`.

- Logguer : `n_pages`, taille PDF, `sys.frozen`, extraction, OCR, regles,
  NER, ecriture texte/audit, recherche des rectangles, rasterisation, save PDF.
- Logguer : `ocr_used`, `ocr_pages_replaced`, `sparse_pages`, `dpi_ocr`,
  `dpi_raster`, `jpeg_quality`, mode worker effectif.
- Logguer : RSS debut/fin/pic si `psutil` disponible, sinon ignorer.
- Risque RGPD : faible. Ne change pas la sortie.

2. Reparalleliser la rasterisation en EXE sans relancer la GUI.

Option a tester en premier : utiliser `ThreadPoolExecutor` uniquement en
`sys.frozen` pour `_rasterize_page`, avec un fallback sequentiel si exception.
Chaque worker ouvre son propre `fitz.open(pdf_path)`, comme aujourd'hui dans
le worker process. Le but est d'utiliser les appels C PyMuPDF/Pillow qui
peuvent liberer le GIL, sans creer de processus qui relancent Tk.

- Cible : `anonymizer_core_refactored_onnx.py:4316-4323`.
- Garde-fou : variable/env ou constante interne pour revenir au sequentiel.
- Risque : moyen-faible, car detection PII inchangee ; risque principal =
  thread-safety PyMuPDF/Pillow a valider sur Windows.

Option plus robuste mais plus lourde : worker mode dedie dans l'EXE
(`--raster-worker`) ou petit exe worker separe, lance sans GUI. A garder pour
v11.5 si le thread pool est instable.

3. Garder le raster securise par defaut, mais ajouter un mode rapide explicite.

Pour MVP, ne pas desactiver silencieusement le raster. Si un mode rapide est
ajoute, il doit etre explicite dans la GUI et dans le log :

- "PDF image securise" par defaut : comportement actuel, sortie raster.
- "Texte anonymise seul / diagnostic rapide" : pas de PDF raster, uniquement
  pour test interne ou cas client accepte.
- "PDF vectoriel rapide" seulement apres leak tests, car du texte residuel PDF
  peut rester si la redaction rate.

Risque : produit/RGPD moyen. Ne pas activer sans decision Dom.

### Correctifs a reporter v11.5 sauf urgence

4. Baisser le DPI OCR de 300 a 200/240 de facon adaptative.

Ne pas le faire en aveugle : risque de rater des petits textes, tampons,
identifiants et scans faibles. A tester contre leak score et OCR low quality.

5. Ajouter un vrai worker Windows pour raster/OCR.

Chantier propre v11.5 : separer GUI et moteur lourd, avec workers sans Tk,
progression et annulation robuste. C'est la meilleure architecture, mais ce
n'est pas un patch rapide.

6. GUI v6 : exposer les profils performance.

La GUI v6 devra rendre visibles les compromis : securite raster, rapide texte,
OCR scanne, logs de performance, estimation temps/pages.

## Plan de benchmark minimal

Bench a faire sur l'EXE Windows, pas seulement Linux/dev.

Jeu minimal :

- PDF natif texte court : 1-2 pages.
- PDF natif texte moyen : 10-20 pages.
- PDF scanne court : 1-2 pages image.
- PDF scanne moyen : 10 pages image.
- PDF reel Dom qui a declenche le symptome.

Pour chaque run :

- redemarrer l'application pour mesurer le premier traitement, puis refaire un
  deuxieme run pour separer warm cache/modeles ;
- noter pages, taille PDF, type natif/scanne ;
- relever duree totale murale, CPU moyen/pic, RAM pic "Private working set" ;
- recopier les lignes `anonymisation.log` : `frozen=`, OCR, durees par etape,
  mode worker raster ;
- verifier les sorties : `*.pseudonymise.txt`, `*.audit.jsonl`,
  `*.redacted_raster.pdf`, quarantaine si applicable.

Comparaisons attendues :

1. Beta actuelle EXE.
2. Beta + timings seulement.
3. Candidate hotfix raster thread pool.
4. Candidate mode rapide explicite, uniquement si Dom valide ce compromis.

## Criteres d'acceptation performance

Gate obligatoire :

- leak score inchange ou meilleur ;
- aucune PII patient dans logs ;
- pas de sortie moins securisee sans choix utilisateur explicite ;
- si worker parallel echoue, fallback sequentiel et log clair.

Gate performance MVP propose :

- sur PDF natif texte, reduction >= 2x du temps total si le goulet etait raster ;
- pendant la phase raster d'un PDF de plus de 4 pages, CPU processus > 40 %
  sur une machine 8 threads, ou au moins 4 pages traitees en parallele logguees ;
- RAM pic native texte <= 6 Go apres chargement modeles ;
- RAM pic OCR scan <= 10 Go sur un PDF scanne de 10 pages A4 ;
- PDF reel Dom : temps divise par au moins 2, sinon P1 non resolu.

Gate UX :

- la GUI affiche/progresse par document et ne semble pas bloquee ;
- le log permet d'identifier l'etape lente sans relancer en mode debug ;
- l'utilisateur voit clairement si OCR/raster est en cours.

## Decision recommandee

Ne pas attendre v11.5 pour ce sujet. La performance doit devenir un hotfix MVP
dedie :

1. autoriser Claude a ajouter instrumentation timings + RSS ;
2. autoriser ensuite un patch raster parallel frozen, priorite thread pool avec
   fallback sequentiel ;
3. demander a Qwen de valider sur benchmarks et leak tests ;
4. ne pas modifier `app_aivanov` dans cette mission ;
5. ne pas changer le mode raster par defaut sans GO Dom explicite.

