Le moteur Turbolog

L’encodage des frames par plages en un appel console.log, le CellBuffer, les détails de Chromium et les benchmarks.

Turbolog transforme chaque commit React en un appel à console.log, ou aucun si aucune cellule n’a changé.

Objectifs

  1. Un appel par frame modifiée.
  2. Zéro appel au repos. Une frame inchangée provoque un retour avant la construction d’une chaîne.
  3. Peu d’arguments de style. 149 spans %c pour les 3200 cellules d’un tableau de bord dense de 100×32.

Pipeline

React ─▶ Yoga ─▶ CellBuffer ─▶ row-hash gate ─▶ RLE ─▶ console.log

CellBuffer

La frame réside dans des tableaux typés plats pour les caractères, les couleurs et les attributs, alloués une seule fois.

Filtrage des changements

Chaque ligne est hachée. Si rien n’a changé, le pilote retourne immédiatement :

if (frame === null) return SKIPPED; // 0 console callsconsole.log(frame.format, ...frame.args);

Remplacement des frames

Turbolog ajoute les frames à la suite et n’efface la console qu’à la première frame, après invalidate(), au repos une fois 100 frames empilées, et à 300. DevTools supprime immédiatement les messages effacés, mais limite l’affichage des nouveaux à un rafraîchissement toutes les 50 ms : effacer chaque frame fait donc brièvement apparaître une console vide. Les frames ajoutées à la suite se remplacent en un seul rafraîchissement, et un span rideau de largeur nulle masque la frame précédente. Faites défiler vers le haut pour voir les frames antérieures.

Les frames sont cadencées à environ 15 fps. Les frames plus rapides réinitialisent la temporisation de DevTools et sont abandonnées.

Codage par plages

Les cellules identiques fusionnent en un seul span %c. Les spans se prolongent au-delà des sauts de ligne, et les chaînes CSS sont internées.

console.log("%c▼ Text.js%c ready", "color:#ededed;font-weight:700", "color:#45a557");

Détails propres à Chromium

  • Le caractère littéral % est échappé sous la forme %%.
  • Les URL et le texte path:line reçoivent un word joiner pour empêcher DevTools de modifier leur style.
  • Les spans utilisent uniquement des propriétés CSS non abrégées. DevTools copie chaque propriété développée sur chaque ligne.
  • Les spans sont ajustés pour que les arrière-plans se juxtaposent sans interstices.

Firefox et Safari

Chromium dispose chaque ligne d’un span %c comme un bloc en ligne. Firefox et Safari conservent les spans en ligne, ignorent donc les marges verticales et renvoient les longues lignes à la ligne. CssConsoleDriver détecte le navigateur par des tests de fonctionnalités CSS et, pour ces deux consoles, définit une hauteur de ligne de 14 px sans marges, désactive le retour à la ligne avec text-wrap-mode: nowrap et repousse les frames antérieures hors de la vue avec un rideau line-height: 100vh. L’ajustement à la console réserve de la place pour la colonne des liens source de Firefox. Safari place Menlo en tête de la liste de polices, car ses pages ne peuvent pas utiliser une police SF Mono installée par l’utilisateur, même si Web Inspector peut l’utiliser pour son affichage. Passez browser à createConsoleRoot pour choisir vous-même une console.

Mesures de performance

packages/core/test/perf.test.ts sur un tableau de bord dense de 100×32, moyenne sur 1000 frames (Apple M5 Pro, Bun 1.4.4) :

FrameTempsSpans %c
Rafraîchissement complet (layout, affichage, encodage)0,163 ms149
Modification d’une ligne0,011 ms149
Au repos0,000 ms0

La page État exécute le même pipeline dans votre navigateur. Exécutez text.stats() dans DevTools pendant qu’une démo du Playground est en cours.

Modifier cette page sur GitHub