Turbolog 引擎
影格如何透過遊程編碼合併為一次 console.log 呼叫,以及 CellBuffer、Chromium 細節與效能測試。
Turbolog 將每次 React 提交轉成一次 console.log 呼叫;若沒有儲存格變更,就不呼叫。
目標
- 每個有變更的影格只呼叫一次。
- 閒置時零呼叫。 未變更的影格會在建立字串之前回傳。
- 少量樣式引數。 密集的
100×32儀表板共有 3200 個儲存格,使用 149 個%cspan。
處理流程
React ─▶ Yoga ─▶ CellBuffer ─▶ row-hash gate ─▶ RLE ─▶ console.logCellBuffer
影格儲存在分別存放字元、顏色與屬性的扁平型別陣列中,只配置一次。
變更檢查閘門
每一列都會計算雜湊值。若沒有變更,驅動程式就提前回傳:
if (frame === null) return SKIPPED; // 0 console callsconsole.log(frame.format, ...frame.args);影格切換
Turbolog 會附加影格,且只在第一個影格、呼叫 invalidate() 後、堆疊達 100 個影格後閒置時,以及達 300 個影格時清除主控台。DevTools 會立即移除已清除的訊息,但新訊息的繪製受 50 ms 的節流限制,因此每個影格都清除會讓主控台閃現空白。附加的影格會在單次繪製內切換,並透過零寬度的遮幕 span 將前一個影格擋在視野之外。向上捲動即可查看先前的影格。
影格更新速率控制在約 15 fps。更快的影格會重設 DevTools 的節流計時,並遭到丟棄。
游程編碼
相符的儲存格會合併成一個 %c span。span 會跨越換行延續,CSS 字串則以字串駐留方式共用。
console.log("%c▼ Text.js%c ready", "color:#ededed;font-weight:700", "color:#45a557");Chromium 細節
- 字面上的
%會跳脫為%%。 - 網址與
path:line文字會插入 word joiner,避免 DevTools 重新設定其樣式。 - span 只使用 CSS 個別屬性。DevTools 會將每個展開後的屬性複製到每一行。
- span 經過調整,讓背景平鋪時不留間隙。
Firefox 與 Safari
Chromium 將 %c span 的每一行配置為行內區塊。Firefox 與 Safari 則讓 span 維持行內顯示,因此會忽略垂直邊距,並將過長的列換行。CssConsoleDriver 透過 CSS 功能檢查偵測瀏覽器,並針對這兩種主控台設定 14 px 行高且不留邊距,使用 text-wrap-mode: nowrap 關閉換行,再以 line-height: 100vh 遮幕將先前的影格推到視野之外。配合主控台尺寸時,會為 Firefox 的來源連結欄預留空間。Safari 將 Menlo 放在字型堆疊的首位,因為網頁無法使用由使用者安裝、但 Web Inspector 可能用來繪製文字的 SF Mono。將 browser 傳給 createConsoleRoot,即可自行選擇主控台。
效能基準測試
packages/core/test/perf.test.ts 在密集的 100×32 儀表板上測試,取 1000 個影格的平均值(Apple M5 Pro,Bun 1.4.4):
| 影格 | 時間 | %c span 數 |
|---|---|---|
| 完整重繪(版面配置、繪製、編碼) | 0.163 ms | 149 |
| 單列編輯 | 0.011 ms | 149 |
| 閒置 | 0.000 ms | 0 |
狀態頁面會在你的瀏覽器中執行相同的處理流程。在 Playground 的示範執行期間,於 DevTools 中執行 text.stats()。