docs: document Lardon3D architecture foundations
This commit is contained in:
parent
d5b6216ef8
commit
6379dce843
2 changed files with 233 additions and 0 deletions
121
docs/architecture/foundation_review.md
Normal file
121
docs/architecture/foundation_review.md
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# Revue technique des fondations
|
||||
|
||||
## Périmètre et conclusion
|
||||
|
||||
Cette revue couvre `task`, `task_queue`, le profil matériel, les snapshots de
|
||||
ressources, le gouverneur, les réservations et leur intégration au scheduler.
|
||||
Aucune fuite, course, interblocage ou violation reproductible de l'invariant
|
||||
d'admission n'a été détecté par l'inspection et les tests actuels. Aucun code de
|
||||
production n'a donc été modifié.
|
||||
|
||||
## Invariants actuellement garantis
|
||||
|
||||
- Une tâche possède une estimation copiée à sa création et exposée seulement
|
||||
par copie.
|
||||
- Le scheduler reçoit explicitement son gouverneur et refuse un gouverneur nul.
|
||||
- Le worker obtient une réservation active avant d'appeler
|
||||
`lardon3d_task_start`; celui-ci revalide la réservation avant le callback.
|
||||
- Un callback lancé par la file dispose d'une copie cohérente de son contrat :
|
||||
lot, RAM, GPU, CPU et slots IO/GPU.
|
||||
- `WAIT` conserve la tâche en tête et endort le worker sur une condition
|
||||
variable. Le mutex de file empêche une notification concurrente de se perdre
|
||||
entre la décision et l'attente.
|
||||
- `REJECT` termine la tâche sans appeler son callback. `REDUCE_BATCH` transmet
|
||||
le contrat réduit.
|
||||
- La réservation détenue par le worker est libérée après succès, échec ou
|
||||
annulation. Une pause en cours conserve volontairement la réservation.
|
||||
- La destruction de la file annule les tâches, réveille et rejoint le worker,
|
||||
puis détruit les tâches dont elle est propriétaire.
|
||||
- Les compteurs du gouverneur et la création des réservations sont protégés par
|
||||
un mutex unique. Une double libération est refusée sans débiter les budgets.
|
||||
- Les calculs de taille contrôlent multiplication et addition ; les compteurs
|
||||
CPU et slots ne peuvent croître au-delà des budgets calculés.
|
||||
- Le profil représente les capacités stables. Les snapshots sont des valeurs
|
||||
datées et indépendantes ; le scheduler ne prend aucune décision de ressources
|
||||
lui-même.
|
||||
|
||||
## Limites connues
|
||||
|
||||
- La file possède un seul worker et applique un FIFO strict. Une tâche en tête
|
||||
qui reçoit `WAIT` bloque les tâches suivantes, même si certaines seraient
|
||||
admissibles.
|
||||
- Une libération extérieure au scheduler exige ensuite un appel à
|
||||
`lardon3d_task_queue_resources_changed`. Le gouverneur ne publie pas encore
|
||||
automatiquement cet événement.
|
||||
- Les réservations libérées restent comme tombstones jusqu'à la destruction du
|
||||
gouverneur. Cela sécurise la double libération mais fait croître la mémoire
|
||||
avec le nombre historique de contrats.
|
||||
- Une erreur de capture du snapshot fait échouer la tâche ; il n'existe pas
|
||||
encore de distinction entre erreur transitoire de mesure et rejet durable.
|
||||
- Le gouverneur et la file doivent être détruits après arrêt de leurs appelants.
|
||||
Leur destruction concurrente avec une API active n'est pas prise en charge.
|
||||
- Les tâches, checkpoints, files et réservations ne sont pas persistés.
|
||||
- Il n'existe ni DAG, ni priorité, ni pool de workers, ni orchestration de
|
||||
séquences adaptatives successives.
|
||||
|
||||
## Risques à surveiller
|
||||
|
||||
- Formaliser l'ordre de durée de vie : la file doit être détruite avant son
|
||||
gouverneur ; une tâche cédée à la file ne doit plus être détruite directement.
|
||||
- Ne jamais permettre à un composant extérieur de libérer la réservation privée
|
||||
du worker. L'appel `get_active` et le démarrage sont sûrs dans le modèle de
|
||||
propriété actuel, pas face à une libération concurrente volontaire.
|
||||
- Éviter qu'un callback détruise ou joigne sa propre tâche, ce qui pourrait
|
||||
attendre sa propre fin.
|
||||
- Conserver les prédicats autour de chaque attente de condition et maintenir le
|
||||
même mutex pour décision `WAIT` et mise en sommeil.
|
||||
- Surveiller les identifiants et compteurs historiques sur les très longues
|
||||
sessions, même si leur débordement est irréaliste avec les allocations
|
||||
actuelles.
|
||||
- Ne pas transformer `MemAvailable`, le swap ou la zram en promesse de mémoire
|
||||
supplémentaire. Les snapshots peuvent déjà refléter une consommation réelle
|
||||
en plus des réservations comptables ; une politique future doit rester
|
||||
conservatrice.
|
||||
- Garder la publication de résultats indépendante du contrat d'exécution : seul
|
||||
un résultat validé atomiquement peut devenir visible.
|
||||
|
||||
## Cohérence documentaire
|
||||
|
||||
Les documents actuels correspondent au code : responsabilités séparées,
|
||||
réservation préalable, pause conservant les ressources, worker unique et
|
||||
notification explicite. La vue d'ensemble décrit comme futurs — et non comme
|
||||
existants — les séquences complètes, la reprise persistante, les snapshots live
|
||||
et le viewer Vulkan.
|
||||
|
||||
## Ordre recommandé des prochains tickets
|
||||
|
||||
1. Formaliser les contrats de propriété, les événements de libération et les
|
||||
erreurs transitoires de snapshot.
|
||||
2. Définir un format de résultat atomique avec identifiant, validation et point
|
||||
de reprise.
|
||||
3. Ajouter l'enchaînement borné de lots adaptatifs sous réservations successives.
|
||||
4. Borner les files et introduire la contre-pression.
|
||||
5. Persister tâches et checkpoints nécessaires à la reprise après crash.
|
||||
6. Ajouter ensuite un DAG minimal, puis les priorités.
|
||||
7. Généraliser vers des pools CPU, IO et GPU en conservant le gouverneur comme
|
||||
unique arbitre.
|
||||
8. Publier des snapshots validés avant d'introduire le viewer séparé.
|
||||
|
||||
## Éléments à ne pas réécrire lors du passage à OpenCode
|
||||
|
||||
- Les structures opaques `Task`, `TaskQueue`, `ResourceGovernor` et
|
||||
`ResourceReservation`.
|
||||
- La séparation profil matériel / snapshot dynamique / politique / réservation.
|
||||
- Le calcul centralisé et protégé des budgets et lots.
|
||||
- L'invariant « réservation active avant callback » et la copie du contrat vers
|
||||
la tâche.
|
||||
- L'annulation coopérative, les checkpoints de pause et la propriété ncurses du
|
||||
thread principal.
|
||||
- Le FIFO à condition variable comme implémentation V1 fiable ; il doit évoluer
|
||||
par extension, pas être remplacé avant que les besoins DAG soient spécifiés.
|
||||
- Les écritures atomiques, rollbacks ciblés et validations déjà utilisés par les
|
||||
projets et imports.
|
||||
- Les tests de concurrence, de double libération, d'annulation et de destruction
|
||||
sûre, qui constituent la base de non-régression.
|
||||
|
||||
## Validation exécutée
|
||||
|
||||
- Suite normale : 10 tests réussis sur 10.
|
||||
- ASan/UBSan : 10 tests réussis sur 10, aucun diagnostic.
|
||||
- TSan : 10 tests réussis sur 10, aucune course signalée.
|
||||
- `git diff --check` : réussi avant la rédaction du présent rapport.
|
||||
112
docs/architecture/overview.md
Normal file
112
docs/architecture/overview.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# Vue d'ensemble de l'architecture Lardon3D
|
||||
|
||||
## Finalité et flux global
|
||||
|
||||
Lardon3D est une application Linux de reconstruction 3D pilotée par une TUI
|
||||
ncursesw. Le terminal reste le centre de contrôle : il gère les projets, lance
|
||||
les opérations, présente leur progression et permet leur annulation. Le futur
|
||||
viewer Vulkan sera un processus ou composant graphique séparé, affiché sur le
|
||||
workspace 8 ; il ne remplacera pas la TUI et ne devra jamais la bloquer.
|
||||
|
||||
```text
|
||||
TUI / Projet
|
||||
↓
|
||||
Task
|
||||
↓
|
||||
Estimate
|
||||
↓
|
||||
Governor
|
||||
↓
|
||||
Reservation
|
||||
↓
|
||||
Scheduler
|
||||
↓
|
||||
Worker
|
||||
↓
|
||||
Résultat atomique
|
||||
↓
|
||||
Viewer live
|
||||
```
|
||||
|
||||
## Composants actuels
|
||||
|
||||
Les projets persistants regroupent leur configuration, les images originales,
|
||||
le manifeste, les résultats de reconstruction, les exports et les journaux.
|
||||
Leur création est protégée contre l'écrasement et les écritures structurantes
|
||||
utilisent des remplacements atomiques.
|
||||
|
||||
L'import d'images s'exécute de manière asynchrone et annulable, sans appel
|
||||
ncurses depuis son worker. Il copie individuellement les fichiers admissibles
|
||||
et maintient un manifeste cohérent. Le catalogue charge et valide ce manifeste
|
||||
en mémoire. La vue d'images en dérive des indices triés et filtrés sans modifier
|
||||
le catalogue, le manifeste ou les images.
|
||||
|
||||
Le moteur de tâches fournit les états, la progression, la pause, l'annulation
|
||||
coopérative et les callbacks. La file actuelle possède un worker unique et
|
||||
respecte l'ordre FIFO. Chaque tâche porte une estimation immuable de ses coûts
|
||||
RAM, GPU, CPU et IO ainsi que des bornes de lot.
|
||||
|
||||
Le profil matériel décrit les capacités stables détectées sur la machine. Les
|
||||
snapshots décrivent les ressources disponibles à un instant donné. Le Resource
|
||||
Governor combine profil, snapshot, marges de sécurité et réservations actives.
|
||||
Il décide si une demande doit démarrer, attendre, réduire son lot ou être
|
||||
refusée, puis matérialise toute admission par une réservation opaque.
|
||||
|
||||
Le scheduler ne décide jamais des ressources. Il demande une réservation au
|
||||
gouverneur juste avant l'exécution et transmet au callback une copie du contrat
|
||||
accordé. L'invariant est strict : aucun callback de tâche n'est lancé sans
|
||||
réservation active validée. Après succès, échec ou annulation, cette réservation
|
||||
est libérée exactement une fois. Une tâche déjà en pause conserve son contrat
|
||||
dans cette première version.
|
||||
|
||||
## Résultats et publication live
|
||||
|
||||
Les traitements futurs fonctionneront par séquences adaptatives : lire un lot
|
||||
borné, calculer, écrire un résultat atomique, libérer la mémoire, puis traiter
|
||||
le lot suivant. La stabilité du système hôte et la réactivité de la TUI ont
|
||||
priorité sur le débit maximal.
|
||||
|
||||
Le viewer live ne devra observer que des snapshots de résultats complètement
|
||||
validés et publiés atomiquement. Il ne lira jamais un fichier intermédiaire et
|
||||
ne partagera pas directement les buffers de travail d'un worker. Une
|
||||
interruption doit laisser le dernier snapshot validé exploitable et permettre
|
||||
la reprise à une frontière de séquence connue.
|
||||
|
||||
## Principes non négociables
|
||||
|
||||
- Aucune tâche lourde monolithique ni chargement complet d'un projet en RAM.
|
||||
- Traitement par séquences adaptatives et libération entre les lots.
|
||||
- Budgets RAM, GPU, CPU et IO explicitement bornés et réservés.
|
||||
- Files de travail et buffers intermédiaires bornés.
|
||||
- La zram est un filet de sécurité, jamais une extension du budget normal.
|
||||
- La RAM partagée des iGPU est comptabilisée dans le budget système.
|
||||
- Écritures atomiques, rollback ciblé et absence de résultat partiellement
|
||||
publié.
|
||||
- Reprise après interruption depuis le dernier état validé.
|
||||
- Viewer live séparé, non bloquant et lecteur de snapshots validés seulement.
|
||||
- Le système hôte, la TUI et les données utilisateur restent prioritaires sur
|
||||
le débit de reconstruction.
|
||||
|
||||
## Limites actuelles
|
||||
|
||||
La file ne possède encore ni DAG, ni priorités, ni pool de workers CPU/IO/GPU.
|
||||
Les tâches et leur progression ne sont pas persistées après un arrêt. Les
|
||||
séquences adaptatives sont préparées par les contrats de lot mais leur
|
||||
enchaînement complet n'est pas encore orchestré. Le viewer Vulkan et la
|
||||
publication live restent à implémenter.
|
||||
|
||||
## Ordre recommandé des prochains tickets
|
||||
|
||||
1. Définir les résultats atomiques, leurs métadonnées de validation et leurs
|
||||
points de reprise.
|
||||
2. Introduire l'exécution d'une tâche en séquences de lots adaptatifs, toujours
|
||||
sous réservations successives.
|
||||
3. Borner explicitement les files et définir la contre-pression entre étapes.
|
||||
4. Persister les tâches, checkpoints et états nécessaires à la reprise après
|
||||
crash.
|
||||
5. Ajouter un DAG minimal et seulement ensuite les priorités.
|
||||
6. Introduire des pools CPU, IO et GPU sans déplacer l'arbitrage hors du
|
||||
gouverneur.
|
||||
7. Publier des snapshots live validés et versionnés.
|
||||
8. Ajouter le viewer Vulkan séparé sur le workspace 8 comme consommateur en
|
||||
lecture seule de ces snapshots.
|
||||
Loading…
Reference in a new issue