Silnik Turbolog

Jak kodowanie długości serii zamienia klatki w jedno wywołanie console.log, a także CellBuffer, szczegóły Chromium i benchmarki.

Turbolog zamienia każdy commit React na jedno wywołanie console.log albo nie wykonuje żadnego, jeśli żadna komórka się nie zmieniła.

Cele

  1. Jedno wywołanie na zmienioną klatkę.
  2. Zero wywołań w bezczynności. Niezmieniona klatka kończy przetwarzanie przed zbudowaniem ciągu znaków.
  3. Niewiele argumentów stylu. 149 spanów %c na 3200 komórek gęstego panelu 100×32.

Potok

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

CellBuffer

Klatka jest przechowywana w płaskich tablicach typowanych na znaki, kolory i atrybuty, alokowanych raz.

Bramka zmian

Dla każdego wiersza obliczany jest hash. Jeśli nic się nie zmieniło, sterownik kończy działanie wcześniej:

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

Podmiana klatek

Turbolog dopisuje klatki i czyści konsolę tylko przy pierwszej klatce, po invalidate(), w bezczynności po zgromadzeniu 100 klatek oraz przy 300 klatkach. DevTools usuwa wyczyszczone komunikaty od razu, ale rysuje nowe z ograniczeniem częstotliwości do 50 ms, więc czyszczenie przy każdej klatce powoduje miganie pustej konsoli. Dopisane klatki podmieniają się w ramach jednego rysowania, a span zasłaniający o zerowej szerokości ukrywa poprzednią klatkę. Przewiń w górę, aby zobaczyć wcześniejsze klatki.

Tempo wyświetlania klatek jest ograniczone do około 15 fps. Szybsze klatki resetują ogranicznik częstotliwości DevTools i są odrzucane.

Kodowanie długości serii

Pasujące komórki łączą się w jeden span %c. Spany przechodzą przez znaki nowego wiersza, a ciągi CSS są internowane.

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

Szczegóły dotyczące Chromium

  • Dosłowny znak % jest zapisywany jako %%.
  • Adresy URL i tekst path:line otrzymują znak word joiner, aby DevTools nie zmieniało ich stylu.
  • Spany używają wyłącznie nieskróconych właściwości CSS. DevTools kopiuje każdą rozwiniętą właściwość do każdego wiersza.
  • Spany są dostrojone tak, aby tła przylegały do siebie bez przerw.

Firefox i Safari

Chromium układa każdy wiersz spanu %c jako blok liniowy. Firefox i Safari zachowują spany jako elementy liniowe, więc ignorują pionowe marginesy i zawijają długie wiersze. CssConsoleDriver wykrywa przeglądarkę przez sprawdzanie obsługi funkcji CSS i dla tych dwóch konsol ustawia wysokość wiersza na 14 px bez marginesów, wyłącza zawijanie za pomocą text-wrap-mode: nowrap i wypycha wcześniejsze klatki poza widok zasłoną line-height: 100vh. Dopasowanie do konsoli pozostawia miejsce na kolumnę odnośników do źródła w przeglądarce Firefox. Safari umieszcza Menlo na początku listy fontów, ponieważ strony tej przeglądarki nie mogą używać zainstalowanego przez użytkownika fontu SF Mono, którym może posługiwać się Web Inspector. Przekaż browser do createConsoleRoot, aby samodzielnie wybrać konsolę.

Testy wydajności

packages/core/test/perf.test.ts na gęstym panelu 100×32, średnia z 1000 klatek (Apple M5 Pro, Bun 1.4.4):

KlatkaCzasSpany %c
Pełne odrysowanie (layout, rysowanie, kodowanie)0,163 ms149
Edycja jednego wiersza0,011 ms149
Bezczynność0,000 ms0

Strona Status uruchamia ten sam potok w twojej przeglądarce. Uruchom text.stats() w DevTools podczas działania dema z Playground.

Edytuj tę stronę w serwisie GitHub