O motor Turbolog

Como os quadros são codificados por comprimento de sequência em uma chamada console.log, além de CellBuffer, detalhes do Chromium e benchmarks.

Turbolog transforma cada commit do React em uma chamada a console.log, ou nenhuma se nenhuma célula mudou.

Objetivos

  1. Uma chamada por quadro alterado.
  2. Zero chamadas quando ocioso. Um quadro sem alterações retorna antes de construir uma string.
  3. Poucos argumentos de estilo. 149 spans %c para as 3.200 células de um painel denso de 100×32.

Pipeline

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

CellBuffer

O quadro fica em arrays tipados planos para caracteres, cores e atributos, alocados uma única vez.

Filtro de alterações

Cada linha recebe um hash. Se nada mudou, o driver retorna antecipadamente:

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

Troca de quadros

Turbolog anexa quadros e limpa o console apenas no primeiro quadro, após invalidate(), quando ocioso depois de acumular 100 quadros, e aos 300. DevTools remove as mensagens apagadas de imediato, mas limita a pintura de novas mensagens a intervalos de 50 ms, então limpar a cada quadro faz o console vazio piscar. Os quadros anexados são trocados em uma única pintura, e um span de largura zero que funciona como cortina mantém o quadro anterior fora de vista. Role para cima para ver os quadros anteriores.

Os quadros são cadenciados a cerca de 15 fps. Quadros mais rápidos reiniciam o intervalo de limitação do DevTools e são descartados.

Codificação por comprimento de sequência

Células iguais se unem em um único span %c. Os spans continuam pelas quebras de linha, e as strings CSS são internadas.

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

Detalhes do Chromium

  • O % literal é escapado como %%.
  • URLs e textos path:line recebem um word joiner para que o DevTools não altere seus estilos.
  • Os spans usam apenas propriedades CSS por extenso. DevTools copia cada propriedade expandida para cada linha.
  • Os spans são ajustados para que os fundos se encaixem sem lacunas.

Firefox e Safari

Chromium dispõe cada linha de um span %c como um bloco inline. Firefox e Safari mantêm os spans inline, então ignoram margens verticais e quebram linhas longas. CssConsoleDriver detecta o navegador com testes de recursos CSS e, para esses dois consoles, define uma altura de linha de 14 px sem margens, desativa a quebra de linha com text-wrap-mode: nowrap e empurra quadros anteriores para fora de vista com uma cortina line-height: 100vh. O ajuste ao console reserva espaço para a coluna de links de origem do Firefox. Safari coloca Menlo em primeiro lugar na lista de fontes, porque suas páginas não podem usar uma SF Mono instalada pelo usuário que o Web Inspector pode usar para desenhar o texto. Passe browser para createConsoleRoot para escolher um console por conta própria.

Benchmarks

packages/core/test/perf.test.ts em um painel denso de 100×32, média de 1.000 quadros (Apple M5 Pro, Bun 1.4.4):

QuadroTempoSpans %c
Repintura completa (layout, pintura, codificação)0,163 ms149
Edição de uma linha0,011 ms149
Ocioso0,000 ms0

A página Status executa o mesmo pipeline no seu navegador. Execute text.stats() no DevTools enquanto uma demonstração do Playground estiver em execução.

Editar esta página no GitHub