simplify-trace

Par tldraw · tldraw

Résume une trace de performance Chrome DevTools volumineuse en un rapport markdown compact, permettant de l'analyser sans charger l'intégralité du fichier. À utiliser lorsqu'on vous fournit une trace Chrome/DevTools/Performance panel (un fichier `Trace-*.json` ou `*.json` de plusieurs Mo contenant des `traceEvents`) et qu'on vous demande d'identifier ce qui est lent, ce qui s'exécute trop souvent, les tâches longues, le jank ou les fonctions JS les plus sollicitées.

npx skills add https://github.com/tldraw/tldraw --skill simplify-trace

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 :

  1. 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.
  2. Réexécutez avec --window START-END autour 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 un file:line — utilisez-le pour localiser la source.

Le script résume seulement ; il ne modifie pas la trace.

Skills similaires