LifePlay-Revival/Docs/Migration/etat/ST/STE/STE-J6-TRACE.md

339 lines
31 KiB
Markdown
Raw Normal View History

Fiche STE-J6-TRACE — Niveau N3 — Modèle prévu opus (xhigh) | utilisé claude-opus-5-5 — Agent lp-cart — Skills sk-protocol, sk-windows-shell (invoqué) ; ue-cpp-build, lp-commandlets, lp-paths préchargés, non utilisés
# STE-J6-TRACE : effet de STE-H10 (trace J6 contre H9) et preuve C0 (2026-10-13) — tentative 2/4
Hors gabarit : sections imposées par la fiche (rubrique 7), à la place du gabarit CART ; notes TRACE (gabarit `lp-doc`) en § 1.
**Résumé de la trace (règle TRACE1)** — trace `D:\Game\LifePlay_Build_5.8_STE-J6_Development\Windows\LifePlay\Saved\Profiling\STE-J6.utrace` (1 534 318 792 o, 2026-10-13 07:36-07:44).
- Contexte : session de jeu J6 de l'utilisateur sur l'archive Development de STE-H10 (A1, B1-a, B2-a, B3-a, B4-a) et C0, même parcours que H9 (J5), comparée à la trace H9.
- Résultat : C0 / ERR-011 établi (groupe F5 du DESTROY 0 / 31 contre 70 / 70), B1-a, B2-a, B3-a atteints (`SavePreset` moyen 53,3 → 31,2 ms), trames Suivant 228 → 134 ms, trames ≥ 50 ms par minute − 12 % ; A1 et B4-a sans gain mesurable.
- Suite : tout commiter (décision de l'utilisateur, 2026-10-13) ; saccades restantes (pièces et lieux, démarrage et carte, génération de PNJ, cheveux de corps) à instruire en H7b / H8b.
**Résultat : réussi.** Chaque critère C.8 et C0 a une mesure H9 et une mesure J6, commande citée, et un verdict ; les limites de
couverture côté H9 sont dites critère par critère (§ 3). En bref :
- **atteints** : B1-a (3 critères), B2-a, B3-a, A1 « au plus un chargement de cheveux par `RandomizeHairs` », Suivant (durée par trame
− 41 %), C0 / ERR-011 ;
- **non atteints** : A1 `RandomizeHairs` max (48,9 ms, seuil 25), A1 `LoadHairMeshIfNeeded` (en hausse), A1 chargements par trame
(trame de démarrage inchangée), trames « sans clic » (pas de baisse), B4-a à la lettre (2 entrées `Current` par trame) ;
- **B4-a** : le corps n'est plus exécuté qu'une fois par fin de scène, mais dans la trame suivante, sans baisse de coût.
Lecture seule ; seul ce fichier est écrit dans le dépôt (plus 17 fichiers ignorés par git dans `STE-J6-TRACE\`, § 7). Abréviations :
- **SP** = `%USERPROFILE%\AppData\Local\Temp\claude\D--Game-LifePlay-master-5-8\36e41eab-6dbf-4c01-adea-9fe53389b8ce\scratchpad\j6t\`
(exports J6, non suivi, perdu à la fermeture de la session) ;
- **H9D** = `%USERPROFILE%\AppData\Local\Temp\claude\D--Game-LifePlay-master-5-8\37530d8d-c780-4a57-8fbd-bcb010aa6408\scratchpad\h9\`
(exports H9 d'origine, du 2026-10-11) ;
- **ST9** = `H9D\stats_gt.csv`, **ST6** = `SP\J6_stats_gt.csv` (ligne du timer citée après `:`).
## 1. Méthode et commandes
### 1.1 Journaux (C0, Accessed None) — acquis de la tentative 1, repris tel quel
`python -I -X utf8 logstats.py J6 "<J6>\LifePlay.log" H9 "<J5 archive>\LifePlay.log" J5 "<J5 archive>\LifePlay-backup-2026.10.10-22.05.32.log"`
(code 0). Sources :
- J6 = `D:\Game\LifePlay_Build_5.8_STE-J6_Development\Windows\LifePlay\Saved\Logs\LifePlay.log` ;
- H9 = `D:\Game\LifePlay_Build_5.8_STE-J5_Development\Windows\LifePlay\Saved\Logs\LifePlay.log` (modifié le 11/10 à 04:59 = fin de H9) ;
- J5 = backup du même dossier.
Méthode de `STE-H4-DIAG.md` § 1 et § 3.1 : motif F5 `GetSocketInfoByName\(([^)]*)\): No SkeletalMesh for Component\(CharacterMesh0\) Actor\(… (Person_C_\d+)\)` ;
motif DESTROY `DESTROY.*index (Person_C_\d+)` ; trame = bloc de lignes consécutives de même `[n]` ; groupe = `Head` ×2, `pelvis`,
`chestUpper`, `hip` du même acteur dans le même bloc. Contrôle : sur J5, le script redonne les chiffres de `STE-H4-DIAG.md:26-34`
(20 493 / 20 488 lignes, 2 816 groupes, 89 DESTROY, 94 SPAWN).
### 1.2 Trace (Insights)
Moteur `D:\Game\Launcher\Engine\UE_5.8\Engine\Binaries\Win64\UnrealInsights.exe`, lancé par `SP\run_pass.ps1` (une trace à la fois,
attente d'une mémoire utilisée ≤ 72 % avant chaque passe, arrêt au premier export vide) :
`pwsh -NoProfile -File "SP\run_pass.ps1" -Pass <qN> -TagList J6 -MaxUsedPercent 72 -WaitMinutes 20`, ligne Insights
`-OpenTraceFile="<trace>" -ABSLOG="SP\insights_<qN>_J6.log" -AutoQuit -NoUI -unattended -nullrhi -ExecOnAnalysisCompleteCmd="@=SP\<qN>_J6.rsp" -log -Messaging`
(celle de H9, `H9D\insights1.log:58`).
| Passe | Fichier de commandes | Mémoire avant (`status.txt`) | Sortie brute (`SP\status.txt`) |
|---|---|---|---|
| q1 | `ExportThreads` ; `ExportTimerStatistics … -threads=GameThread -columns=*` ; `ExportTimingEvents … -threads=GameThread -columns=TimerName,StartTime,EndTime,Depth -timers=FEngineLoop::Tick,ContinueScene,RandomizeHairs,…,BndEvt*,InpActEvt*,*MouseButton*` (32 motifs) | 66,3 % | `08:02:27 END q1 J6 code=0 duree=65s exports=3` ; `insights_q1_J6.log:319` 68 threads, `:324` statistiques, `:330` `Exported 150298 timing events` |
| q2 | par trame ≥ 50 ms : `lf` = commande H9 à l'identique (`… -startTime -endTime -sortby=totalexclusivetime -sortorder=descending -maxtimercount=60`, `H9D\pass2.rsp:1`) ; `la` = même commande sans tri ni plafond | 65,6 % | `08:04:37 END q2 J6 code=0 duree=55s exports=228` (114 + 114) |
| q3 | `ExportTimingEvents` complet (GameThread) de 11 trames J6 longues (8 sans clic, 2 autre clic, 1 Suivant ; choix par `p4_tree.py sel`) | 66 % | `08:10:39 END q3 J6 code=0 duree=60s exports=11` |
| q4 | idem, 3 trames contenant `RandomizeHairs` (`p5_rh.py rsp`) | 65,2 % | `08:12:39 END q4 J6 code=0 duree=45s exports=3` |
Aucun échec Insights pendant cette tentative (4 passes sur J6, toutes `code=0`, exports au compte). **H9 : aucune passe lancée**
(consigne de l'orchestrateur : essai H9 économisé). Les exports H9 d'origine sont dans H9D et servent tels quels :
- `tick.csv` (`H9D\pass1.rsp:3`) : 31 758 trames ; recalcul des trames ≥ 50 ms identique à `H9D\long.csv` (120 lignes, sortie
`long.csv H9 : 120 lignes ; identique aux trames recalculees : True`) ;
- `stats_gt.csv` (`H9D\pass1.rsp:2`, même commande que q1 plus `-sortby=totalinclusivetime -sortorder=descending -maxtimercount=400`,
qui ne change que l'ordre et la troncature) : les lignes relues redonnent les références de `STE-H10-SPEC.md` § 1.1 (ST:261,
375, 155, 102, 152, 159) ;
- `lf_000…119.csv` (même commande que `lf` J6) ; `ev_*.csv` (8 trames Suivant, `H9D\pass3.rsp`) et `nc_*.csv` (4 trames,
`H9D\pass4.rsp`), exportés par `ExportTimingEvents` comme `J6_sel.csv` mais sur 12 trames seulement.
Analyse (lecture seule des CSV) :
- `python -I -X utf8 SP\p1_analyse.py crit J6 H9` (code 0) : session, catégories, statistiques, critères événementiels ;
- `SP\p3_complements.py` : catégories règle B, B4-a trame par trame, contenu de `RandomizeHairs` ;
- `SP\p4_tree.py tree` et `SP\p5_rh.py tree` : arbre d'appels reconstruit par profondeur, chemin critique, chaîne de chaque
`LoadPackageInternal`.
Corrections demandées :
1. `p1_analyse.py` réécrit (Write complet) : profondeur minimale calculée une fois ; copie inutile retirée de `inside()` ; analyse
H9 en 15 s (`real 0m15.241s`).
2. `run_pass.ps1` prend déjà `-TagList` en `[string]` découpé par `-split ','` ; toutes les passes ont une seule étiquette.
`SP\insights_p1_J6,H9.log` (essai 0) laissé en place (aucune suppression).
3. Chemin vide de l'essai 0 : même cause (point 2) ; les lignes START de q1 à q4 portent le chemin complet de la trace.
Notes TRACE :
```
Trace : SP\J6_*.csv (q1-q4) — Fiche STE-J6-TRACE — 2026-10-13 08:01-08:12
Commande : § 1.2 (run_pass.ps1, q1_J6.rsp … q4_J6.rsp), trace D:\Game\LifePlay_Build_5.8_STE-J6_Development\Windows\LifePlay\Saved\Profiling\STE-J6.utrace
Environnement: copie 5.8, branche ue5.8 (HEAD 9eaa6cc à l'ouverture de la session), UnrealInsights UE 5.8 ; aucun éditeur ouvert (orchestrateur) ; mémoire utilisée 65,2-66,3 % avant chaque passe
Attendu : au moins une ligne « TraceInsights: Exported » par commande (3, 228, 11, 3)
Obtenu : exports=3, 228, 11, 3 ; code=0 x4 (status.txt l. 7-14)
Lecture : -sortby=totalexclusivetime n'a pas d'effet : J6_lf_005.csv:2-8 suit l'ordre des timers (FEngineLoop::Tick, FEngineLoop_HeartBeat, Frame…), pas un tri ; -maxtimercount=60 garde donc les 60 premières lignes de cet ordre (§ 2)
Trace : H9D\*.csv — exports d'origine STE-H9 — 2026-10-11 03:00-03:10 UTC
Commande : H9D\pass1.rsp à pass4.rsp, trace D:\Game\LifePlay_Build_5.8_STE-J5_Development\Windows\LifePlay\Saved\Profiling\STE-H9.utrace
Environnement: machine calme (insights1.log sans alerte mémoire)
Attendu : redonner STE-H9-TRACE.md § 2 et STE-H10-SPEC.md § 1.1
Obtenu : stats identiques ; catégories 18 / 76 / 26 contre 18 / 78 / 24 (§ 2)
Lecture : événements complets sur 12 trames seulement (8 Suivant + 4) : critères événementiels H9 limités à ces trames
```
## 2. Catégories de trames H9 / J6
Session (FEngineLoop::Tick) :
| | H9 | J6 |
|---|---|---|
| Trames | 31 758 ; 545,6 s (9,09 min) | 28 163 ; 481,9 s (8,03 min) |
| Trames ≥ 50 ms | 120 ; 18,57 s ; médiane 92,0 ms | 114 ; 14,47 s ; médiane 77,5 ms |
| Par minute de jeu | 13,20 trames ; 2,043 s | 14,19 trames ; 1,802 s (**− 12 %** de temps saccadé par minute) |
Catégorie d'une trame : `ContinueScene` présent → Suivant ; sinon un gestionnaire de clic → autre clic ; sinon sans clic. Deux
règles de clic, et un piège de méthode :
- **règle A** (gestionnaire nommé : `BndEvt*`, `InpActEvt*`, `*LeftMouseInput`, `*ClickButton*`) : elle redonne H9 § 2 à 2 trames
près (18 / 76 / 26 contre 18 / 78 / 24) ;
- **règle B** : règle A plus tout `*MouseButton*` (`ProcessMouseButtonUp` seul compte comme clic) ;
- **piège** : les fichiers `lf` (commande H9) ne gardent que les 60 premières lignes dans l'ordre des timers (note TRACE § 1).
Un gestionnaire enregistré tard dans la session n'y figure pas. Sur J6, `lf` et `la` (tous les timers) classent différemment
30 trames sur 114 en règle A, 13 en règle B. `la` et les événements de session (`sel`) donnent le même classement. Pour H9, seul
`lf` existe.
Mesures (sortie de `p1_analyse.py crit` et `p3_complements.py`) :
| Catégorie | H9 `lf` règle A | J6 `lf` règle A | H9 `lf` règle B | J6 `lf` règle B | J6 `la` / `sel` (exact) |
|---|---|---|---|---|---|
| Suivant : n ; total ; médiane ; moyenne | 18 ; 4,10 s ; 217,5 ; 228,0 ms | 11 ; 1,48 s ; 137,8 ; 134,3 ms | 18 ; 4,10 s | 11 ; 1,48 s | 12 ; 1,67 s ; 138,7 ; 139,2 ms |
| Suivant par min (n ; s) | 1,98 ; 0,451 | 1,37 ; 0,184 | 1,98 ; 0,451 | 1,37 ; 0,184 | 1,49 ; 0,208 |
| Sans clic : n ; total ; médiane ; moyenne | 76 ; 10,48 s ; 81,2 ; 138,0 ms | 82 ; 9,80 s ; 74,1 ; 119,6 ms | 69 ; 10,07 s ; 85,9 ; 146,0 | 65 ; 8,84 s ; 83,3 ; 135,9 | 53 ; 7,78 s ; 83,0 ; 146,7 ms |
| Sans clic par min (n ; s) | 8,36 ; 1,153 | 10,21 ; 1,221 | 7,59 ; 1,108 | 8,09 ; 1,100 | 6,60 ; 0,968 |
| Autre clic : n ; total ; médiane | 26 ; 3,99 s ; 87,4 ms | 21 ; 3,19 s ; 76,2 ms | 33 ; 4,40 s ; 82,3 | 38 ; 4,16 s ; 66,9 | 49 ; 5,03 s ; 67,9 ms |
| Autre clic par min (n ; s) | 2,86 ; 0,438 | 2,61 ; 0,397 | 3,63 ; 0,484 | 4,73 ; 0,518 | 6,10 ; 0,626 |
Lecture, à méthode égale (colonnes `lf`) :
- **Suivant** : la baisse est nette et ne dépend pas de la règle. Moyenne par trame 228,0 → 134,3 ms (− 41 %), maximum 399,7 →
188,5 ms, temps par minute 0,451 → 0,184 s.
- **Sans clic** : aucune baisse. Règle A : + 22 % de trames par minute et + 6 % de temps par minute, moyenne par trame 138,0 →
119,6 ms. Règle B : temps par minute stable (1,108 → 1,100 s).
- **Cheveux** : une seule trame sans clic « due aux cheveux » dans chaque session, celle de démarrage (§ 3, A1).
- La répartition sans clic / autre clic dépend de la règle et de la troncature ; seul le total et Suivant sont robustes.
## 3. Critères § C.8 (mesure H9 → mesure J6 → seuil → verdict)
Seuils : `STE-H10-SPEC.md` § C.8 (l. 649-667) et § 7 (l. 408-409) pour « chargements par trame ». Statistiques = ST9 / ST6 (même
calcul : `Incl / Count`) ; événements J6 = toute la session (`J6_sel.csv`) ; événements H9 = 12 trames (`ev_*`, `nc_*`).
| Critère | H9 | J6 | Seuil | Verdict |
|---|---|---|---|---|
| A1 `RandomizeHairs` max | 38,4 ms ; n=34 ; moy. 16,96 ms (ST9:261) | **48,9 ms** ; n=30 ; moy. 19,83 ms (ST6:6699) | < 25 ms | **non atteint** |
| A1 chargements de cheveux (`getSkeletalMeshFromPath` chargeant) par `RandomizeHairs` | non mesurable : 0 `RandomizeHairs` dans les 12 trames d'événements H9 | 0 sur 30 appels (aucun `getSkeletalMeshFromPath` sous `RandomizeHairs`) | ≤ 1, sauf rejet | **atteint** (J6 seul) |
| A1 `LoadHairMeshIfNeeded` appels / inclusif | 108 ; 284,6 ms (ST9:375) | **119 ; 778,8 ms** ; max 34,4 ms (ST6:7250) | en baisse | **non atteint** |
| A1 chargements de cheveux par trame | 87 dans une trame (t=4,231 s, 304,8 ms, `nc_1`) ; 0 ailleurs dans les 12 trames | 87 dans une trame (t=6,419 s, 799,3 ms) ; **0 dans toutes les autres trames** | aucune trame > 2 (§ 7 l. 408) | **non atteint** (trame de démarrage, inchangée) |
| B1-a `RevertStripAll` sous `SavePreset`, `DestroyPerson` suivis d'un `destroyDummy` | 10 / 10 ; 308,2 ms (ev_*, 8 trames ; § 1.2 de la SPEC : 5 / 5) | **0 / 4** (session) ; garde G3 : 0 `RevertStripAll` hors `SavePreset` | 0 | **atteint** |
| B1-a ces `SavePreset` | 23,7 à 89,1 ms ; moy. 60,8 (n=10) | 24,1 à 41,5 ms ; moy. 33,8 (n=4) | ≤ 45 ms | **atteint** |
| B1-a `SavePreset` moyen | 53,25 ms ; max 89,1 ; n=29 (ST9:155) | **31,21 ms** ; max 59,1 ; n=12 (ST6:6386) | ≤ 35 ms | **atteint** |
| B2-a `GetSMBoolForSMC_Cloth` moyen par appel | 2,17 ms (3 017,6 / 1 393 ; max 17,1 ; ST9:102) | **1,40 ms** (1 252,6 / 895 ; max 3,8 ; ST6:7179) | ≤ 1,5 ms | **atteint** |
| B3-a `ClearProxies` moyen par appel | 8,13 ms (1 610,4 / 198 ; ST9:152) | **5,82 ms** (850,0 / 146 ; ST6:6502) | ≤ 6,1 ms | **atteint** |
| B4-a `Current` par trame de fin de scène | 2 dans 7 / 7 trames (ev_*) ; corps exécuté 2 fois (`CopyActionsToScroll` 2) | 2 entrées dans 6 / 6 trames ; corps 0 dans la trame, **1 fois dans la trame suivante** (6 / 6) | ≤ 1 | **non atteint à la lettre** ; intention (un seul corps) atteinte |
| B4-a coût par fin de scène | `Current` 34,2 à 113,4 ms ; moy. 72,5 ms (7 trames) | corps différé 29,4 à 106,0 ms ; moy. 77,2 ms ; trame suivante ≥ 50 ms 4 fois sur 6 | — (§ 1.3 : − 38 ms par trame) | **pas de gain** ; coût reporté |
| Global : Suivant, durée par trame | 228,0 ms ; 18 trames ; 0,451 s/min (`lf`) | 134,3 ms ; 11 trames ; 0,184 s/min (`lf`) ; 139,2 ms ; 12 trames (`la`) | en baisse | **atteint** |
| Global : trames sans clic dues aux cheveux | 1 trame (démarrage, 304,8 ms) | 1 trame (démarrage, 799,3 ms) | en baisse | **non atteint** |
| Global : toutes catégories | 120 ; 18,57 s ; 2,043 s/min | 114 ; 14,47 s ; 1,802 s/min | — | baisse de 12 % du temps saccadé par minute |
| Visuels (cheveux, PNJ habillés, liste d'actions, états « exposé ») | — | « pas de défauts constatés » (verdict oral, aucune capture) | captures | **estimé** favorable, non prouvé |
Détails établis (sorties de `p3_complements.py`, `p4_tree.py`, `p5_rh.py`) :
- **A1 `RandomizeHairs` max**. Le cheveu de tête n'est plus chargé dans `RandomizeHairs`. Les appels les plus longs contiennent un
chargement synchrone de **cheveux de corps**, hors périmètre de A1 :
`RH t=412.869 48.9 ms … randomizeDazBHair 29.0 ; setBHairstyle 29.0 ; GetAsset 28.9 ; LoadPackageInternal 28.8 … UpdateProxyMorphs 16.2`,
chaîne `GetAsset < setBHairstyle < randomizeDazBHair < ExecuteUbergraph_Person` ; même forme à t=141,879 s (44,5 ms, chargement
28,1 ms).
- Sur la session : `LoadPackageInternal (externes) par appel : {0: 15, 1: 13, 2: 2} ; total LPI sous RH=178.0 ms`.
- Les 2 appels à 2 chargements sont aussi sous `setBHairstyle` (2,7 + 1,7 ms) : ce ne sont pas des rejets de cheveu de tête.
- Appelant : `RandomizeAll < GeneratePerson`, sous `ExecuteUbergraph_Room` (actions latentes) ou `ReadSceneLine`. 29 des 30
appels tombent dans une trame ≥ 50 ms.
- Contenu de `RandomizeHairs` en H9 : non relevé (aucun export d'événements de ses trames). Que `randomizeDazBHair` chargeait déjà
en H9 est **estimé** : A1 ne touche que la boucle des cheveux de tête (`STE-H10-SPEC.md:493-551`).
- **A1 `LoadHairMeshIfNeeded`**. Dans les deux sessions, presque tous les chargements de cheveux tombent dans une seule trame de
démarrage, sous `ExecuteUbergraph_Person` (préchargement) :
- H9 : `LoadHairMeshIfNeeded (externes) n=89 incl=284.6 ms chargeants=87`, trame t=4,231 s (`nc_1`) ; cette trame porte tout
l'inclusif de session (ST9:375 : 284,6 ms) ;
- J6 (`J6_tr_002.csv`) : `LoadHairMeshIfNeeded 779 ms x89 ; … LoadPackageInternal 772 ms x87 ; FlushAsyncLoading 770 ms x87 ; MainThreadWaitingOnAsyncLoadingThread 740 ms x383`.
- Même travail (87 paquets), mais attente du thread de chargement 2,7 fois plus longue. Cause **incertaine** : cache disque froid
de l'archive J6 neuve, estimé, non mesuré.
- Hors de cette trame, J6 n'a **aucun** chargement de cheveux de tête (distribution `{87: 1}`).
- **B4-a** : trames de fin de scène J6 (`p3_complements.py`), par exemple
`t=106.522 trame=120.9 ms Current=2 TopRight=0.0 ms CopyActions=0 | trame suivante=123.6 ms TopRight=106.0 ms CopyActions=1 (14.8 ms) Current=0`.
Dans la trame suivante (`J6_tr_014.csv`), le corps différé passe surtout par la carte :
`ExecuteUbergraph_TopRight 106 > LeftMouseInput 90 > ExecuteUbergraph_StreetMap_Static 90 > ActualLeftMouseInput 90`
(`Array_Get` ×28 624). Le regroupement 2 → 1 ne diminue presque rien : l'essentiel du coût est exécuté une fois de toute façon
(estimé).
- **Couverture H9** : B1-a, B4-a et chargements par trame H9 = 12 trames d'événements. Leurs valeurs sont un échantillon (les 8 trames
Suivant les plus lourdes, plus 4 trames sans clic) ; les valeurs J6 couvrent la session. Les moyennes par appel et les pointes
restent comparables ; les comptes, non.
## 4. C0 / ERR-011 (journaux) — acquis de la tentative 1
Sortie brute de `logstats.py` (extraits) :
```
== J6 : lignes=9937 premier=2026.10.13-05.36.08:852 dernier=2026.10.13-05.44.16:956 blocs_trame=2965
"No SkeletalMesh" (toutes lignes)=3343 ; F5 LogSkinnedMeshComp=3338
F5 par socket : {'CenterBrow': 528, 'Head': 1124, 'pelvis': 562, 'chestUpper': 562, 'hip': 562}
groupes de 5 (Head x2, pelvis, chestUpper, hip) par bloc et acteur = 562
DESTROY=31 ; index SPAWN=36
DESTROY avec groupe F5 dans la trame du DESTROY (meme bloc, meme acteur) = 1 / 31 ; ex. lignes [3698]
DESTROY avec groupe dans la trame suivante (bloc+1) = 19 / 31
== H9 : lignes=24367 premier=2026.10.11-02.49.50:715 dernier=2026.10.11-02.59.00:217 blocs_trame=8328
"No SkeletalMesh" (toutes lignes)=16005 ; F5 LogSkinnedMeshComp=16000
F5 par socket : {'Head': 3893, 'pelvis': 1960, 'chestUpper': 1960, 'hip': 1960, 'CenterBrow': 6227}
groupes de 5 (Head x2, pelvis, chestUpper, hip) par bloc et acteur = 1938
DESTROY=70 ; index SPAWN=75
DESTROY avec groupe F5 dans la trame du DESTROY (meme bloc, meme acteur) = 69 / 70 ; ex. lignes [1657, 1692, 2338]
DESTROY sans groupe dans leur trame = 1 ; ex. lignes [8968]
DESTROY avec groupe dans la trame suivante (bloc+1) = 46 / 70
== J5 : "No SkeletalMesh" (toutes lignes)=20493 ; F5 LogSkinnedMeshComp=20488 ; groupes = 2816 ; DESTROY=89 ; index SPAWN=94
DESTROY avec groupe F5 dans la trame du DESTROY (meme bloc, meme acteur) = 89 / 89
```
Les deux exceptions, relues à la main :
- **J6:3698** (`DESTROY… Person_C_2147481859`, motif « from CheckScenes, WHO unmatched ») : les 4 lignes F5 du bloc `[ 90]`
(J6:3692-3695) sont **avant** le `SPAWN` (J6:3697) et le DESTROY ; elles appartiennent à la réserve précédente. Le groupe
suivant arrive dans la trame `[ 91]` (J6:3700-3704). Donc **0 / 31** DESTROY J6 ont un groupe après leur ligne dans leur trame.
- **H9:8968** : le groupe est bien dans la trame du DESTROY, mais il ne compte que 4 lignes (`Head` ×1, H9:8969-8972). Donc
**70 / 70** DESTROY H9 ont des lignes F5 juste après eux dans la même trame.
| | J5 | H9 | J6 |
|---|---|---|---|
| DESTROY avec groupe F5 dans leur trame, après la ligne DESTROY | 89 / 89 | 70 / 70 (dont 1 groupe de 4) | **0 / 31** |
| F5 total (LogSkinnedMeshComp) | 20 488 | 16 000 | 3 338 |
| F5 par DESTROY | 230,2 | 228,6 | 107,7 |
| Groupes par DESTROY | 31,6 | 27,7 | 18,1 |
| `CenterBrow` | 6 408 | 6 227 | 528 |
| DESTROY suivis d'un groupe dans la trame suivante | 58 / 89 | 46 / 70 | 19 / 31 |
**Verdict C0 / ERR-011 : groupe disparu (établi).** Aucun DESTROY de J6 n'a son groupe de 5 lignes dans sa trame ; dans H9 et J5,
tous l'ont. Les groupes des trames suivantes restent (19 / 31), comme prévu (`STE-H4-C0-SPEC.md:16`, « hors C0 »).
La baisse attendue d'environ 5 × 31 = 155 lignes F5 est **compatible** avec ces chiffres, mais **non isolable**. La baisse totale
(107,7 contre 228,6 lignes par DESTROY) dépasse de loin 5 lignes par DESTROY. Elle vient surtout de `CenterBrow` (528 contre 6 227)
et de moins de groupes par DESTROY (18,1 contre 27,7), qui dépendent du parcours. La part de C0 dans cette baisse reste **incertaine**.
## 5. `Accessed None` (J6 contre H9, et J5) — acquis de la tentative 1
Sortie brute (`AN <n> <fonction> | <propriété> | l. <lignes>`) :
```
J6 : 12 lignes, 8 couples
AN 5 /Game/BPs/GI.GI_C:isCreatureType | Actor | l. [5126, 7325, 7666]
AN 1 /Game/BPs/GI.GI_C:SavePreset | CallFunc_GetSkeletalMesh_ReturnValue_3 | l. [1230]
AN 1 /Game/BPs/PC.PC_C:ExecuteUbergraph_PC | CallFunc_getFirstDick_Person_1 | l. [2643]
AN 1 /Game/UI/CharGen.CharGen_C:PopulateGenitalSlidersDaz | CallFunc_GetSkeletalMesh_ReturnValue | l. [1280]
AN 1 /Game/UI/CityMenu.CityMenu_C:ExecuteUbergraph_CityMenu | GI | l. [1381]
AN 1 ? | Actor / CallFunc_GetSkeletalMesh_ReturnValue / CallFunc_GetSkeletalMesh_ReturnValue_# | l. [9884, 9890, 9894]
H9 : 24 lignes, 9 couples
AN 9 isCreatureType | Actor ; AN 8 /Game/BPs/GI.GI_C:getRelatedPerson | Per | l. [1898, 1909, 2046]
AN 1 PC ExecuteUbergraph_PC ; AN 1 CharGen PopulateGenitalSlidersDaz ; AN 1 CityMenu ExecuteUbergraph_CityMenu ; 4 lignes « ? » (l. 24311-24326)
J5 : 43 lignes ; dont AN 1 /Game/BPs/GI.GI_C:SavePreset | CallFunc_GetSkeletalMesh_ReturnValue_3 | l. [1154]
```
Les lignes « ? » sont des lignes sans `Function` à la suite, en fin de journal (résumé ; estimé : le résumé `LogLifePlay`).
| Fonction / propriété | H9 | J6 | Classement |
|---|---|---|---|
| `GI.SavePreset` / `CallFunc_GetSkeletalMesh_ReturnValue_3` | 0 | 1 (J6:1230, avant la partie) | **Préexistant**, non traité : présent dans J5 (J5:1154, avant H10 : établi) et, d'après l'orchestrateur, dans STC et H5b-TEMOIN ; absent de H9 : variation de parcours (estimé) |
| `GI.getRelatedPerson` / `Per` | 8 | 0 | Disparu ; dépend du parcours (estimé, aucun lien avec H10 établi) |
| `GI.isCreatureType` / `Actor` | 9 | 5 | Présent dans les deux |
| `PC`, `CharGen`, `CityMenu` | 1 / 1 / 1 | 1 / 1 / 1 | Inchangés |
| `GI.GetSMBoolForSMC_Cloth` | 0 | **0** | Point (1) de `STE-H10-VAL.md` vérifié : aucun `Accessed None` nouveau sur ce parcours (établi) |
| Autres graphes de H10 (`RandomizeHairs`, `ClearProxies`, `DestroyPerson`, `TopRight`) | 0 | 0 | Aucun nouveau (établi pour ce parcours) |
## 6. Saccades restantes : les 5 premières causes en J6
Sources :
- part = inclusif cumulé dans les 114 trames ≥ 50 ms (14,47 s), fichiers `la` (`p3_complements.py`, scopes moteur génériques
exclus) ; les parts **se recouvrent** (inclusif) ;
- chaînes = arbres reconstruits de 11 trames détaillées (`J6_tr_*.csv`, `p4_tree.py`) ;
- comparaison H9 impossible à méthode égale (fichiers `lf` H9 tronqués à 60 timers, § 2).
| # | Cause (chaîne établie dans les trames détaillées) | Part inclusive | Trames | Exemples (trame, durée : chaîne) |
|---|---|---|---|---|
| 1 | **Pièces et lieux** : `ExecuteUbergraph_Room` (minuteries et actions latentes) → `LoadRoom` / `LoadPreset` / `setBackground3D`, `AfterLoadRoom` → `getStandSpots` → `removeTooClose`, `refreshIdleDummies` | 2,912 s, 20,1 % (`AfterLoadRoom` 1,027 s, 7,1 %) | 77 (`AfterLoadRoom` : 8) | tr_110, 532,7 ms : `AfterLoadRoom 515 > getStandSpots 383 > removeTooClose 365` ; tr_097, 239,4 ms : `ActionDurationUpdate > StopDurationUpdate > MatchCurrentPlayerBuilding > … > LoadRoom 160 > AfterLoadRoom 129` ; tr_096, 138,2 ms (clic d'action) : `PlayerGoHere > TakeModActionWithBuilding > PlayDaily > ShowCurrentWorldPreset > setBackground3D > LoadPreset > LoadRoom 65` |
| 2 | **Démarrage, nouvelle partie, ville** (ponctuel) : `DelayedStart` → `LoadSettings` → `PopulateRaws` ; `LoadCity` → `MoveCity` → `SpawnMapMarkers` → `ActualSpawnMarkers` | 1,343 s (9,3 %) + 1,316 s (9,1 %) | 1 + 2 | tr_009, 1 350,9 ms : `SpawnMapMarkers 1263`, `ExecuteUbergraph_MapMarkers` ×49 422, `AddMarker` ×49 417, `FindCenterOfPolygon` ×49 425 |
| 3 | **Génération de PNJ et lancement de scène** : `UpdateCheckForScenes` → `PlayScene` → `ReadSceneLine` → `SceneStart` / `GeneratePerson` → `assignWork`, `assignHome`, `RandomizeAll` ; `GenerateRecs` → `recommendActions` → `SearchByAmenitySafe` | `GeneratePerson` 1,291 s (8,9 %) ; `ReadSceneLine` 1,280 s (8,8 %) ; `SearchByAmenitySafe` 0,510 s exclusif (3,5 %) | 28 ; 22 ; 11 | tr_076, 272,9 ms : `PlayScene 244 > ReadSceneLine 134 > SceneStart 134 > OpenSpace 110 > refreshIdleDummies 102` ; tr_093, 223,2 ms : `ReadSceneLine > GeneratePerson 145 > assignWork 48` ; tr_104, 195,2 ms : `GenerateRecs 117 > recommendActions 117`, `SearchByAmenitySafe` 110 ms ×3 |
| 4 | **Chargements synchrones sur le GameThread** : `GetAsset` → `LoadPackageInternal` → `FlushAsyncLoading` → `MainThreadWaitingOnAsyncLoadingThread` | 1,193 s (8,2 %) ; attente 1,152 s exclusif (8,0 %) | 29 | tr_002, 799,3 ms : préchargement de 87 cheveux (§ 3) ; `RandomizeHairs` → `randomizeDazBHair` → `setBHairstyle` → `GetAsset` : 178 ms sur 30 appels, jusqu'à 28,8 ms |
| 5 | **Clic « Suivant » et liste d'actions** : `ContinueScene` → `ReadSceneLine`, `clearScenePersons` → `DestroyPerson` → `SavePreset` / `RevertStripAll` → `IsGenitalExposed` → `GetSMBoolForSMC_Cloth` ; puis le corps différé de `TopRight` (→ `StreetMap_Static.LeftMouseInput`) dans la trame suivante | `ContinueScene` 1,220 s (8,4 %) ; corps différé ≈ 0,4 s (4 trames de 103 à 124 ms) | 12 + 4 | tr_060, 193,5 ms (Suivant) ; tr_014, 123,6 ms : `ExecuteUbergraph_TopRight 106 > LeftMouseInput 90` |
Transversal : `Array_Get` exclusif 1,992 s (13,8 %, 112 trames). Ce sont les boucles Blueprint de toutes les causes ci-dessus
(`MapMarkers`, `removeTooClose`, `StreetMap_Static`…). S'y ajoutent `ClearAllExpressions` (0,850 s, 52 trames) et
`IsGenitalExposed` → `GetSMBoolForSMC_Cloth` (0,84 à 0,89 s, 71 trames).
Par catégorie (`la`, règle A) :
- sans clic (7,78 s) : `ExecuteUbergraph_Person` 39,5 %, `ExecuteUbergraph_Room` 35,2 %, ville 16,9 %, chargements synchrones
14,1 %, `GeneratePerson` 14,0 %, `AfterLoadRoom` 13,2 % ;
- Suivant (1,67 s) : `ContinueScene` 73,0 %, `ReadSceneLine` 40,7 %, `clearScenePersons` 25,3 %, `SavePreset` 19,5 %.
## 7. Écarts et incertitudes
Écarts à la fiche et aux consignes :
- **H9 sans nouvel export** (consigne de l'orchestrateur, qui prime sur la rubrique 3 « refais les exports H9 ») : statistiques,
trames et fichiers `lf` H9 d'origine, de même commande que J6 ; critères événementiels H9 limités à 12 trames (§ 3). Le seul
critère sans valeur H9 : chargements par `RandomizeHairs`. Une passe `q1` sur H9 le donnerait (1 essai restant).
- **Méthode des outils** : j'ai lu l'état des passes et listé le scratchpad avec `ls`, `grep`, `tail`, `cat`, `wc` en Bash, au lieu
de Read / Grep / Glob (consigne de l'agent). Lecture seule, sans effet sur les fichiers.
- **Copie** dans `D:\Game\LifePlay-master 5.8\Docs\Migration\etat\ST\STE\STE-J6-TRACE\` (permise par les rubriques 3 et 6) de 17
fichiers : scripts `.py` / `.ps1`, fichiers de commandes `.rsp`, `status.txt`, journaux Insights. Ils sont ignorés par git :
`git check-ignore -v` → `.gitignore:75:/Docs/Migration/etat/**` ; `git status --porcelain --untracked-files=all -- …STE-J6-TRACE`
→ vide. Aucun CSV copié : les exports J6 (dont `J6_tr_009.csv` 144 Mo) restent dans SP. On les refait en 4 min environ avec
q1 à q4 et la trace de l'archive J6. Ces fichiers contiennent des chemins absolus du poste ; non suivis, non publiés.
- Scripts du scratchpad à usage répété (`sk-protocol` § 7) : `p4_tree.py` (arbre d'appels par profondeur) est à proposer pour `Tools/`.
Incertitudes et non mesuré :
- **Catégories** : la règle d'H9 § 2 n'est pas connue exactement (18 / 76 / 26 redonné, contre 18 / 78 / 24). Les fichiers `lf`
tronqués faussent la répartition sans clic / autre clic (§ 2). Seuls Suivant et le total sont robustes.
- **Trame de démarrage des cheveux** 304,8 → 799,3 ms : même nombre de paquets, attente du thread de chargement plus longue ; cause
non mesurée (cache froid estimé).
- **H9 `RandomizeHairs`** : contenu non relevé ; présence de `randomizeDazBHair` en H9 estimée.
- **Parcours différents** (manuels) : 31 DESTROY en J6 contre 70 en H9, 51 `ContinueScene` contre 65, 6 fins de scène contre 7
(détaillées). Les comptes et les totaux ne se comparent pas ; les moyennes par appel, les pointes et les valeurs par minute, oui.
- **Plafond de 100 lignes de `-LPHitchLog`** (tentative 1) : toujours incertain, non relu.
- **Critères visuels** : verdict oral seulement (estimé).
Fichiers écrits :
- ce livrable ;
- dans SP : `q1_J6.rsp` à `q4_J6.rsp`, `p1_analyse.py` (réécrit), `p3_complements.py`, `p4_tree.py`, `p5_rh.py`, exports `J6_*.csv`
(par Insights), `J6_long.csv`, `insights_q1…q4_J6.log`, `status.txt` (par `run_pass.ps1`) ;
- copies ignorées par git dans `STE-J6-TRACE\`.
Fichiers à commiter : M `Docs/Migration/etat/ST/STE/STE-J6-TRACE.md` (dépôt du jeu, branche `ue5.8` ; ajouté non suivi en tentative 1,
donc A s'il n'a pas encore été commité).
Tours : 30 / 60
## Constats
- À verser : `lp-env` (section « mesure Insights »), avec le constat de la tentative 1 sur la mémoire à 80 % (4 passes réussies à
65-66 %) :
- `ExportTimerStatistics -sortby=totalexclusivetime` reste sans effet ; avec `-maxtimercount=N`, l'export garde les N premières
lignes dans l'ordre des timers (`J6_lf_005.csv:2-8`). Une catégorie par présence d'un timer dans ce fichier manque les timers
enregistrés tard (30 trames sur 114 reclassées). Exporter sans `-maxtimercount`.
- Pour les causes, `ExportTimingEvents` complet d'une trame, plus un arbre reconstruit par `Depth`, donne la chaîne d'appel
(`p4_tree.py`, 3,7 millions d'événements lus pour une trame de 1,35 s).
- À verser : `sk-windows-shell` — attendre en avant-plan un outil lancé en arrière-plan, sans `sleep` :
`pwsh -NoProfile -Command "Wait-Process -Name UnrealInsights -Timeout 900 -ErrorAction SilentlyContinue"`.
- Pour la suite (H7b / H8b, décision de l'orchestrateur) :
- A1 n'a pas visé la bonne charge : les chargements de cheveux de tête sont un préchargement de démarrage (une trame dans les deux
sessions) ;
- le coût restant de `RandomizeHairs` vient de `randomizeDazBHair` → `setBHairstyle` → `GetAsset` (chargement synchrone) et de
`UpdateProxyMorphs` ;
- B4-a reporte le coût sans le réduire : le corps différé passe surtout par `StreetMap_Static.LeftMouseInput` (90 ms sur 106).