Preserve formatted NAND boot and Wii Remote pairing, add DMA/SRAM conformance tests and a Wii comparison probe. Keep P1 profiling tools and native update A/B evidence; reject the unhelpful targeted SRAM shortcut.
292 lines
20 KiB
Markdown
292 lines
20 KiB
Markdown
# Protocole P1 — attribuer les ralentissements Wii LLE
|
||
|
||
Date : 19 septembre 2026. Statut au 22 septembre : **capture noyau locale validée ;
|
||
coût du collecteur, cas PPC et chemin critique Wii non qualifiés**.
|
||
Aucune nouvelle mise à jour n'est lancée par la rédaction de ce document.
|
||
Il remplace la stratégie « modifier, refaire une mise à jour, comparer les FPS ».
|
||
|
||
## 1. Question et règle de décision
|
||
|
||
Sur les passages réellement lents, déterminer **quel travail ou quelle attente retarde
|
||
la progression de l'émulation**, dans quelles fonctions, et pour combien de temps.
|
||
Le résultat attendu n'est pas « un cœur à 100 % », mais une attribution vérifiable.
|
||
|
||
Une seule exécution de diagnostic est prévue après qualification du dispositif.
|
||
Aucun nouveau correctif de performance avant un rapport d'attribution exploitable.
|
||
Une capture incomplète ne justifie pas un correctif au hasard : on répare le dispositif,
|
||
et on précise quelle information manque avant d'envisager une capture complémentaire.
|
||
Une seule cause est ensuite traitée ; la validation porte d'abord sur sa charge locale.
|
||
|
||
## 2. Pourquoi A–F ne suffisent pas
|
||
|
||
- Les instantanés espacés d'environ 10 secondes ne décrivent ni les pics ni leurs piles.
|
||
- Les FPS échantillonnés ne sont pas une distribution des temps de frame.
|
||
- Un nombre d'accès mémoire ou d'instructions JIT ne mesure pas leur coût CPU.
|
||
- `ARMCore::RunCycles` contient également `m_bus.AdvanceCycles` : son temps inclusif
|
||
ne doit pas être présenté intégralement comme du calcul ARM.
|
||
- `AdvanceCycles` appelle les périphériques, dont OHCI et le réseau : additionner
|
||
ces temps imbriqués compterait plusieurs fois le même travail.
|
||
- `Sampler.cpp` utilise `SuspendThread`/`ResumeThread` ; ses observations historiques
|
||
ne deviennent pas une référence de temps sans perturbation.
|
||
- Le lecteur F ne résout pas certaines adresses JIT. Une annotation absente n'est
|
||
ni zéro travail JIT ni une preuve que tous les autres offsets sont incorrects.
|
||
- Les 600–2 700 Mo de journal sont des repères approchés, pas une charge identique.
|
||
- La durée entre messages utilisateur n'est pas la durée exacte de la mise à jour.
|
||
- Les conditions hôte/serveur diffèrent. F est observé plus lent que E, mais la cause
|
||
n'est pas isolée. Répéter simplement F avec un autre réglage ne résout pas cela.
|
||
|
||
## 3. Geler le scénario, sans toucher aux NAND existantes
|
||
|
||
Le diagnostic concerne le ralentissement actuel : source actuelle figée correspondant
|
||
au comportement F, profilage détaillé des accès désactivé, **sans nouvelle optimisation**.
|
||
Créer une build de diagnostic propre, non incrémentale, et ne pas remplacer les builds
|
||
figées D/E/F. Conserver le patch et les empreintes des sources, y compris les fichiers
|
||
non suivis utilisés, options de compilation, compilateur, EXE, PDB et paramètres.
|
||
Vérifier l'identité EXE/PDB ; cela ne suffit pas, à elle seule, à valider un lecteur de types.
|
||
|
||
Utiliser un nouveau profil depuis la graine pré-mise à jour déjà vérifiée :
|
||
SHA256 `07b2f4bc543cfd4203efc448538505e9d503b2727c16aaff8d8c0b286d8b4f0c`.
|
||
Conserver les mêmes réglages Wii, réseau NAT, rendu, vitesse 100 %, horloges invitées,
|
||
SD et persistance. Noter les différences de chemins et rien d'autre.
|
||
Un démarrage du processus n'implique pas un cache disque Windows froid ; ne pas vider
|
||
les caches système, changer l'affinité ou désactiver l'antivirus pour fabriquer un résultat.
|
||
|
||
Relever au départ et pendant la capture : charge des autres processus, CPU logique utilisé,
|
||
état d'alimentation, fréquence disponible, mémoire/pression de pagination, disque et GPU.
|
||
Ne pas lancer de compilation, benchmark, hachage massif, nettoyage ou autre test en parallèle.
|
||
Ne pas fermer des applications utilisateur sans accord. Si un concurrent perturbe une fenêtre,
|
||
la signaler et mesurer sa contribution plutôt que l'effacer du rapport.
|
||
|
||
## 4. Deux couches de mesure sur la même horloge
|
||
|
||
### A. Profil système Windows, indépendant des layouts C++
|
||
|
||
WPR, Xperf et WPA sont présents sur cette machine ; `wpr -profiles` a été vérifié.
|
||
Employer un profil ETW ciblé, validé avant le test :
|
||
|
||
- CPU échantillonné avec piles, cible initiale 1 ms, intervalle réellement utilisé consigné ;
|
||
- changements de contexte et réveils, pour séparer **Running / Ready / Waiting** par thread ;
|
||
- chargement des modules, événements disque/fichiers, fautes matérielles de pagination ;
|
||
- métadonnées d'activité réseau, sans contenu des paquets ;
|
||
- fréquence/puissance si disponibles. Une donnée absente reste « indisponible ».
|
||
|
||
Les vues CPU échantillonné et CPU précis répondent à des questions différentes : localisation
|
||
du calcul d'une part, ordonnancement/attentes d'autre part. Les combiner, sans confondre une
|
||
pile d'attente avec une preuve d'attente disque. [Documentation Microsoft](https://learn.microsoft.com/en-us/troubleshoot/windows-server/support-tools/support-tools-xperf-wpa-wpr)
|
||
|
||
Ne plus utiliser de suspension de thread ou d'attachement au débogueur pour chronométrer.
|
||
Pas de profilage heap complet, trace de chaque accès mémoire, ni capture de paquets par défaut.
|
||
Filtrer l'analyse sur le PID/TID exact et conserver les processus concurrents pour expliquer
|
||
le temps Ready. Ne pas supposer que le PID suffit après un redémarrage : enregistrer sa date
|
||
de création. Aucun arrêt/annulation d'une session ETW tierce ; vérifier les sessions avant démarrage.
|
||
|
||
### B. Télémétrie native légère, versionnée
|
||
|
||
Publier les compteurs depuis le code qui les possède ; ne plus les déduire d'offsets PDB
|
||
via `ReadProcessMemory`. Un schéma versionné comporte `run_id`, version, QPC/fréquence,
|
||
PID/TID, génération du cœur/rechargement IOS et des compteurs monotones.
|
||
L'export asynchrone est borné ; les débordements sont comptés. Aucune écriture de log
|
||
synchrone à chaque instruction ou accès. Ne pas ajouter de verrou partagé au chemin mémoire.
|
||
Récupérer les données sur leur thread propriétaire, sans lecture C++ concurrente non synchronisée.
|
||
|
||
- Temps invité écoulé et cycles ARM/PPC, séparés du temps hôte QPC.
|
||
- Temps de frames réellement produites : histogramme p50/p95/p99 et longues frames,
|
||
rapporté au mode vidéo du profil (50 ou 60 Hz). Une médiane de FPS n'est pas ce calcul.
|
||
- Agrégats toutes les secondes ; chronologie d'analyse en fenêtres de 250 ms quand
|
||
les événements le permettent. Marquer les fenêtres qui n'ont pas assez de données.
|
||
- JIT : compilations, invalidations, instructions natives/fallback, accès lents existants,
|
||
entrées en attente et sorties de slice, avec identifiant de génération après reset.
|
||
- NAND : lectures/programmes/effacements, transactions, octets et erreurs ; séparer
|
||
sérialisation/hash, appels d'écriture, `IOFile::Flush` et attente hôte observée.
|
||
- Réseau : octets/trames hôte reçus, mise en file NAT, remise USB à IOS, occupation maximale
|
||
et âge des files. Le débit reçu ne prouve pas le débit consommé par IOS.
|
||
|
||
Les chronomètres de régions fréquentes sont échantillonnés et calibrés, jamais posés sur
|
||
chaque accès ARM. Les frontières plus rares (rechargement, compilations, gros transferts)
|
||
peuvent produire des événements. Éviter un échantillonnage périodique aligné sur la boucle
|
||
invitée ; conserver le taux de sélection et distinguer estimation et total exact.
|
||
|
||
### C. Rendre les échantillons JIT attribuables
|
||
|
||
Un PDB décrit le C++ compilé, pas automatiquement le code généré à l'exécution.
|
||
Exporter, à compilation/invalidation, les intervalles d'adresses **hôte** du JIT ARM et
|
||
du JIT PPC, dispatcher/trampolines compris, avec QPC et génération ; pour les blocs,
|
||
indiquer PC invité, ARM/Thumb et identité du mapping. Ne pas extraire ni publier le firmware.
|
||
Une adresse réutilisée après vidage du cache doit se résoudre selon la date de l'échantillon.
|
||
|
||
Classer l'IP feuille même si la pile ne traverse pas correctement une transition JIT/C++.
|
||
Ne pas inventer de parent de pile manquant. Garder « pile tronquée » et « code non attribué »
|
||
visibles ; ajouter une instrumentation ciblée si ces trous empêchent la décision.
|
||
Le support `Common::JitRegister` existant côté PPC est un point d'intégration à examiner,
|
||
pas une garantie que le JIT ARM ou l'unwinding Windows sont déjà couverts.
|
||
|
||
## 5. Points d'attribution dans ce dépôt
|
||
|
||
| Domaine | Points à observer | Preuve recherchée |
|
||
|---|---|---|
|
||
| Ordonnancement ARM | `Starlet::RunSlice`, `ARMCore::RunCycles` | Coût de dispatch, quanta/s, transitions, temps invité/hôte |
|
||
| JIT ARM | `ARMJitX64::Run`, compilation, code généré, helpers | Part CPU feuille, blocs invités chauds, recompilations |
|
||
| Mémoire ARM | `ReadMemorySlow`, `WriteMemorySlow`, traduction, bus | CPU exclusif des helpers et classes d'accès, pas leur seul nombre |
|
||
| Périphériques | `StarletMemory::AdvanceCycles`, DMA, AES/SHA, OHCI/EHCI | CPU exclusif par fonction ; attente simulée séparée du travail hôte |
|
||
| NAND | `CommitNANDPages`, `NANDJournal::Append`, `IOFile::Flush` | CPU de préparation vs appels fichiers vs attente disque réelle |
|
||
| Réseau | `SlirpNetwork::Poll`, AX88772, remise OHCI | CPU NAT/USB, files, progression hôte versus progression invitée |
|
||
| PPC / rendu | JIT PPC, threads vidéo, présentation | Concurrence réelle et dépendances de l'émulation, pas seulement FPS |
|
||
| Hors émulation | Limiteur, audio, logs, collecteur, Windows | Attente voulue, contention, CPU de diagnostic, temps Ready |
|
||
|
||
Sur un même thread, présenter les **temps exclusifs** des régions imbriquées.
|
||
Présenter aussi leurs temps inclusifs, mais dans une autre colonne, non additionnable.
|
||
Ne pas additionner le CPU de plusieurs threads comme une durée murale de mise à jour.
|
||
Pour les attentes, suivre la dépendance qui retarde le thread utile ; un thread GPU qui
|
||
attend l'émulation n'est pas une cause de ralentissement GPU.
|
||
`fflush` n'est pas une preuve de vidage physique sur disque : le niveau de persistance
|
||
actuel reste inchangé et les attentes sont établies par les événements hôte.
|
||
|
||
## 6. Qualification obligatoire, sans demander de mise à jour à l'utilisateur
|
||
|
||
Avant de dire « lance la mise à jour », un contrôle local court doit démontrer :
|
||
|
||
1. EXE/PDB identifiés ; compteur versionné lu correctement ; horloges alignées ; un reset
|
||
ne produit pas de deltas négatifs ; pas de perte silencieuse d'événements.
|
||
2. Une boucle JIT connue est correctement attribuée ARM/PPC ; son coût CPU augmente
|
||
comme prévu. Un cas d'attente connu est classé Waiting, pas « calcul JIT ».
|
||
3. Les scopes imbriqués d'un test ont des temps exclusifs cohérents, sans double comptage.
|
||
4. Un cas de journal synthétique et de réseau local, sans service Nintendo, est visible.
|
||
5. Mesurer le surcoût ON/OFF du dispositif complet sur la même charge locale, dans le même
|
||
binaire et en ordre alterné. Budget initial : **2 %** de temps mural/CPU, bruit affiché.
|
||
Ce seuil est une règle de projet, pas une garantie d'ETW. S'il est dépassé ou non résolu
|
||
par le bruit, alléger les fournisseurs/samples avant le test. Le contrôle ne garantit
|
||
pas le même surcoût sur toutes les phases natives : relever aussi la charge du collecteur.
|
||
|
||
Pas de nouveau comportement invité, pas de changement de NAT, timers, JIT, NAND ou SVC.
|
||
Les boucles SVC/polling éventuelles sont d'abord attribuées à du CPU/PC invité ; aucune
|
||
émulation accélérée d'appel IOS ne découle d'un simple comptage d'instructions.
|
||
|
||
## 7. Une capture native, puis analyse hors ligne
|
||
|
||
1. Vérifier réserve disque et absence de test/build actif. Enregistrer le manifeste.
|
||
2. Armer ETW et la télémétrie **avant** de lancer le profil isolé ; confirmer une fenêtre
|
||
visible et des mesures valides. Ne pas se baser sur les messages utilisateur pour armer.
|
||
3. L'utilisateur lance une seule mise à jour. Garder 10 s de référence avant l'activité.
|
||
Tout marquage manuel reste approximatif ; les phases sont reconstruites à partir des
|
||
événements synchronisés, files réseau, travail invité et commits NAND.
|
||
4. Téléchargement, calcul et installation peuvent se chevaucher : ne pas leur imposer
|
||
trois phases exclusives artificielles. Une file vide ne prouve pas une attente serveur.
|
||
5. Garder environ 10 s après la réussite signalée, puis arrêter uniquement la capture.
|
||
Ne pas arrêter Dolphin, modifier la NAND ou cliquer à la place de l'utilisateur.
|
||
6. Garde-fous initiaux : 15 min de capture, budget disque 4 Gio et réserve 5 Gio ; le pilote
|
||
doit arrêter proprement **sa** capture si une limite approche, conserver le préfixe et
|
||
déclarer les phases manquantes. Une trace incomplète n'est pas un échec de la mise à jour.
|
||
7. Vérifier les événements perdus et le coût du profilage. Ne pas charger WPA ni effectuer
|
||
une grosse analyse/hachage pendant la mesure. Fermer ensuite Dolphin avec l'utilisateur
|
||
pour les vérifications NAND, comme pour F.
|
||
|
||
Les traces en mode fichier sont adaptées à ce scénario contrôlé, mais ajoutent des E/S :
|
||
les distinguer du journal NAND, relever le volume et ne pas supposer leur coût nul.
|
||
Les pertes d'événements rendent certaines conclusions impossibles ; les vérifier explicitement.
|
||
[Sessions ETW/WPR — Microsoft](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/sessions)
|
||
|
||
## 8. Rapport exigé avant tout correctif
|
||
|
||
Analyser la capture entière et, au minimum, trois fenêtres lentes non chevauchantes de
|
||
10 s si elles existent, ainsi qu'une fenêtre rapide de la même exécution. Une fenêtre lente
|
||
est définie avant analyse : vitesse invitée moyenne < 90 % pendant au moins 2 s ; analyser
|
||
aussi les longues frames indépendamment. Rapporter l'absence de fenêtres admissibles.
|
||
Comparer des types d'activité similaires ; ne pas comparer une pause réseau à une installation.
|
||
|
||
Livrer :
|
||
|
||
- Chronologie superposant vitesse/frames, CPU Running/Ready/Waiting, NAND et files réseau.
|
||
- Top fonctions/piles, part CPU exclusive/inclusive, nombre d'échantillons, contexte invité.
|
||
- Temps critique perdu en calcul, Ready et attentes expliquées ; catégories inconnues visibles.
|
||
- Coût par unité de travail quand disponible : CPU/transaction, CPU/Mio traité, compilations
|
||
par instruction, etc. Un compteur n'a de sens que pour la même opération/sémantique.
|
||
- Liste des observations qui réfutent les autres pistes ; distinguer preuve et hypothèse.
|
||
|
||
Gates de qualité initiaux : zéro perte sur les flux indispensables à l'intervalle analysé,
|
||
au moins 95 % des échantillons CPU Dolphin attribués à un domaine, compteurs intègres et
|
||
coût de collecte qualifié. Ce sont des critères d'analyse, non des promesses de précision.
|
||
Une pile incomplète peut permettre de classer un domaine sans identifier sa cause interne :
|
||
on ne valide alors pas un correctif visant une fonction non résolue. Pas de fausse certitude
|
||
statistique obtenue en traitant des échantillons temporels corrélés comme des essais indépendants.
|
||
|
||
Un correctif est admissible seulement si :
|
||
|
||
1. La cause apparaît dans plusieurs fenêtres lentes avec une signature explicable.
|
||
2. Sa part sur le chemin qui retarde l'émulation est chiffrée, avec son incertitude.
|
||
3. Un cas local représentatif reproduit cette charge ou cette attente.
|
||
4. Le gain global plausible est estimé avant modification. Par exemple, supprimer tout un
|
||
poste responsable de 5 % du temps critique ne retire au mieux que 5 % de cette durée.
|
||
5. Le correctif garde le comportement matériel et passe les tests ciblés/interpréteur.
|
||
|
||
Décision pratique : si le CPU est dans les helpers, travailler ces helpers ; s'il est
|
||
dans le code invité, examiner les blocs et le travail IOS ; si Ready domine, étudier
|
||
la contention hôte ; si les attentes d'E/S dominent, traiter leur dépendance réelle.
|
||
Si les files NAT sont pleines mais peu consommées, ne pas accuser le serveur ; si elles
|
||
sont vides, confirmer l'attente avec les échanges/états disponibles ou laisser la cause ouverte.
|
||
Si aucun poste ne domine, le rapport le dit : on ne fabrique pas un unique responsable.
|
||
|
||
## 9. Validation minimale après diagnostic
|
||
|
||
D'abord une validation locale répétable du poste identifié, résultat invité exact et même
|
||
charge. Puis une validation native ciblée du scénario corrigé, pas une série de réglages.
|
||
La trace de diagnostic peut localiser une cause, mais son temps n'est pas automatiquement
|
||
une référence équitable face à une build sans instrumentation. Pour revendiquer un gain
|
||
global, conserver un dispositif équivalent et répéter seulement si la variabilité observée
|
||
empêche la conclusion. Annoncer cette nécessité et sa raison, pas un nouveau test à l'aveugle.
|
||
L'objectif est de réduire les essais utilisateur ; garantir à l'avance qu'un seul essai
|
||
prouvera toute causalité serait trompeur.
|
||
|
||
## 10. Artefacts et limites
|
||
|
||
Conserver dans un nouveau répertoire local ignoré : manifeste, capture ETL, télémétrie
|
||
versionnée, mapping JIT daté, coût de collecte, tableaux de fenêtres, piles chaudes,
|
||
rapport des attentes, événements perdus et décision. Le rapport lisible va dans `docs`.
|
||
Pas de clés NAND, mémoire brute invitée, mots de passe ou contenu réseau dans les exports.
|
||
Les ETL peuvent contenir des chemins et noms de processus : conservation locale, pas de push.
|
||
|
||
État au 22 septembre 2026 : instrumentation opt-in `DOLPHIN_PERF_TRACE=1`, mapping
|
||
temporel JIT ARM/PPC, scopes/counters versionnés, profil WPR ciblé, décodeur ETL et
|
||
sonde locale ont été ajoutés. La build isolée passe et la sonde privée a validé
|
||
13 contrôles locaux sur 13 sur deux captures, avec zéro perte d'événement.
|
||
Sur deux paires alternées, la phase ARM avec trace privée dépasse la phase sans
|
||
trace d'environ 1,7 % en moyenne, mais la dispersion est supérieure à cet écart.
|
||
Le budget de 2 % n'est donc pas qualifié. Le démarrage/arrêt du logger privé
|
||
ajoute environ 0,34 s à ces exécutions courtes ; ce coût ne mesure pas le
|
||
surcoût du collecteur WPR pendant une mise à jour Wii.
|
||
La session WPR ne démarrait pas dans le jeton Windows de cette tâche
|
||
(`0xc5585011`, droit de profilage système absent). Une capture synthétique
|
||
administrateur a depuis produit l'ETL `P1-local-004`, sans perte. L'analyse
|
||
hors ligne, reproductible sous PowerShell 5.1, valide 9 427 échantillons CPU,
|
||
694 context-switches, dix ancres QPC alignées à cinq ticks près, et le sommeil
|
||
connu effectivement classé `Waiting`. Le PDB local résout les fonctions C++;
|
||
le mapping temporel attribue les IP du JIT ARM. Les 112 événements Xperf
|
||
invalides sont des métadonnées `ImageID` hors du PID cible. Voir
|
||
[`Tools/PerformanceTrace/README.md`](../Tools/PerformanceTrace/README.md).
|
||
Le lot WPR `P1-overhead-001` a terminé ses huit charges synthétiques sans perte
|
||
ETW ; seul son calcul final a échoué faute de Python dans le PowerShell
|
||
administrateur. Le calcul récupéré hors ligne donne quatre écarts ARM ON/OFF de
|
||
+9,7 %, +25,0 %, -0,5 % et +1,0 %, tandis que les quatre bases OFF ont une
|
||
étendue de 34,5 %. Cette variabilité interdit d'annoncer un coût fiable du
|
||
collecteur ou de qualifier le seuil de 2 %. Le script vérifie maintenant Python
|
||
avant toute capture et peut analyser un lot déjà enregistré avec `-AnalyzeOnly`.
|
||
Les traces ON montrent en outre un indexeur C++ hôte (`cpptools.exe`) actif
|
||
pendant chaque essai et des services Dell intermittents. Le profil a été allégé
|
||
des piles `ReadyThread`, tout en conservant leurs événements ; sa nouvelle
|
||
version n'est pas encore qualifiée par un lot ON/OFF stable.
|
||
Le second lot avec ce profil (`P1-overhead-002`) a conservé zéro perte ETW mais
|
||
36,5 % d'étendue entre bases OFF. L'analyse par processeur montre que la sonde
|
||
rapide passe 78,7 % de ses échantillons sur les logiques 0–3 contre 28,9 % pour
|
||
la sonde la plus lente ; les temps ARM correspondants sont 7,59 et 10,33 s.
|
||
L'ETL identifie un i7-1255U hybride avec SMT sur 0–3. Le lanceur Wii fixait
|
||
déjà Dolphin à ces processeurs, mais les sondes OFF/ON ne l'étaient pas.
|
||
L'affinité a été ajoutée aux sondes et vérifiée localement (masque 15 observé).
|
||
Quatre bases fixées gardent toutefois 8,3 % de dispersion ARM ; elles ne
|
||
valident pas encore le seuil initial de 2 %. Il serait trompeur de demander un
|
||
troisième lot administrateur sans résoudre cette variabilité résiduelle.
|
||
Les événements natifs ne sont pas activés dans les profils utilisateur par défaut.
|
||
Une build et une sonde locale réussies ne valident pas le budget de 2 % ni le
|
||
comportement d'une mise à jour native. Le vérificateur local conserve
|
||
`native_update_ready=false` tant que les gates PPC, chemin critique natif et
|
||
coût du collecteur n'ont pas été validées.
|
||
**Ne pas demander de nouvel essai utilisateur tant que ces gates ne passent pas.**
|