Simplifier trace
Les traces de performance Chrome DevTools font des dizaines à des centaines de MB de JSON — bien trop volumineux pour être lus directement. Cette skill en transforme une en un rapport markdown de quelques KB qui met en avant le travail qui prend trop de temps ou qui se reproduit trop souvent.
Usage
Exécutez le script sur le fichier trace. Il affiche du markdown sur stdout (ou --out FILE) :
node skills/simplify-trace/scripts/simplify-trace.mjs <trace.json> [--top N] [--long-task-ms MS] [--window START-END] [--out report.md]
--top N— lignes par tableau (défaut 25).--long-task-ms MS— seuil de long-task (défaut 50).--window START-END— limiter le rapport à un intervalle de temps (décalages en ms depuis le début de la trace).--only a,b/--except a,b/--all— choisir les sections à émettre.--match TEXT— filtre insensible à la casse pour les lignes (noms d'événements, noms de fonctions, URLs).--list— afficher les clés de section disponibles et quitter.--out FILE— écrire dans un fichier au lieu de stdout.- Traces de plus de ~500 MB : préfixer avec
node --max-old-space-size=8192.
Par défaut, exécutez avec --out vers un fichier temporaire pour les grandes traces, puis lisez le rapport. Ne lisez pas la trace brute.
Sections
Sections par défaut : summary, longtasks, events, frequent, functions, categories. Opt-in : timeline (temps principal-thread occupé par seconde — pour localiser l'activité), network (waterfall ressource/fetch avec TTFB/durée/taille), websocket (cycle de vie WebSocket — doc /app/file sync). Exécutez --list pour l'ensemble complet. Interrogez de manière ciblée, par exemple :
# où est l'activité ? puis limitez-la
node …/simplify-trace.mjs trace.json --only timeline
# que faisaient network/socket lors de l'action ?
node …/simplify-trace.mjs trace.json --only network,websocket --window 62000-69000 --match tldraw
Le metadata.startTime de la trace (ISO/UTC) ancre le décalage 0 à l'heure murale, ainsi les décalages de trace peuvent être alignés sur les logs serveur (zero-cache, sync-worker) par timestamp. Pour un intervalle inactif et silencieux réseau, la trace montre quand mais pas pourquoi — ajoutez performance.mark()/console.timeStamp() dans le chemin client et ils apparaissent sur la timeline de la trace.
Traces « What happens when I do X »
Un enregistrement d'une seule action (changer de fichier, ouvrir un menu) est surtout du temps d'initialisation inactif, ce qui étale l'action sur toute la trace. Limitez plutôt à l'action :
- Exécutez une fois sans window. Notez où se trouve l'activité — les décalages des long tasks, ou le temps principal-thread occupé par seconde dans un script inline rapide pour trouver l'intervalle actif.
- Réexécutez avec
--window START-ENDautour de cet intervalle. Tous les tableaux ne décriront alors que l'action.
L'artefact d'enregistrement CpuProfiler::StartProfiling (le profiler qui s'active, ~50–60ms) est exclu du tableau long-task, y compris quand il est imbriqué dans un RunTask. Si long tasks affiche « None », l'action n'a véritablement pas de tâche bloquante unique — regardez plutôt le temps self agrégé, GC et les événements de boucle d'animation.
Ce que contient le rapport
- Header — nombre d'événements, intervalle mural, temps JS CPU échantillonné et pourcentage inactif.
- Long tasks — tâches de haut niveau au-dessus du seuil (jank principal-thread), avec le décalage temporel où chacun s'est produit.
- Types d'événement les plus chauds (self time) — où va réellement le temps engine/navigateur (layout, GC, paint, appels de fonction), excluant le temps passé dans les enfants imbriqués.
- Types d'événement les plus fréquents (count) — travail qui se reproduit trop souvent.
- Fonctions JS les plus chaudes — self time bottom-up depuis le profil CPU V8 embarqué, avec
file:line. Les frames synthétiques(idle)/(program)sont exclues ici (idle est dans le header). - Self time par catégorie — répartition haut niveau entre les catégories de trace.
Comment le lire
- Une fonction haute en self time est le coût réel ; total haut mais self bas signifie que le coût est dans ses callees — suivez l'arbre d'appels.
- Count haut avec moyenne basse = mort par mille coupures (souvent une boucle réactive/render qui se déclenche trop souvent) ; enquêtez sur pourquoi elle se déclenche, pas sur son coût par appel.
- Les long tasks pointent quand le jank s'est produit ; référencez le décalage contre ce que l'utilisateur faisait.
- Les noms minifiés (
r,Tg) viennent avec unfile:line— utilisez-le pour localiser la source.
Le script résume seulement ; il ne modifie pas la trace.