موتور Turbolog

نحوهٔ کدگذاری طول اجرای فریم‌ها در یک فراخوانی console.log، به‌همراه CellBuffer، جزئیات Chromium و بنچمارک‌ها.

⁦Turbolog⁩ هر کامیت React را به یک فراخوانی console.log تبدیل می‌کند، یا اگر هیچ سلولی تغییر نکرده باشد، هیچ فراخوانی‌ای انجام نمی‌دهد.

هدف‌ها

  1. یک فراخوانی به‌ازای هر فریم تغییریافته.
  2. صفر فراخوانی در حالت بیکار. فریم بدون تغییر پیش از ساختن رشته بازمی‌گردد.
  3. آرگومان‌های سبک‌دهی کم. ⁦149 span⁩ از نوع %c برای 3,200 سلول یک داشبورد متراکم 100×32.

خط پردازش

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

CellBuffer

فریم در آرایه‌های نوع‌دار تخت برای نویسه‌ها، رنگ‌ها و ویژگی‌ها نگهداری می‌شود که حافظهٔ آن‌ها یک بار تخصیص می‌یابد.

دروازهٔ تشخیص تغییر

هر ردیف هش می‌شود. اگر چیزی تغییر نکرده باشد، درایور زودتر بازمی‌گردد:

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

تعویض فریم

⁦Turbolog⁩ فریم‌ها را به انتها اضافه می‌کند و کنسول را فقط در اولین فریم، پس از فراخوانی invalidate()، هنگام بیکاری پس از انباشته شدن 100 فریم و در فریم 300 پاک می‌کند. DevTools پیام‌های پاک‌شده را بلافاصله حذف می‌کند، اما پیام‌های جدید را با محدودیت زمانی 50 ms ترسیم می‌کند؛ بنابراین پاک کردن کنسول در هر فریم باعث می‌شود کنسول خالی لحظه‌ای دیده شود. فریم‌های افزوده‌شده در یک نوبت ترسیم جایگزین می‌شوند و یک span پرده‌ای با عرض صفر، فریم قبلی را از دید خارج نگه می‌دارد. برای دیدن فریم‌های قبلی به بالا پیمایش کنید.

آهنگ نمایش فریم‌ها حدود 15 fps است. فریم‌های سریع‌تر محدودیت زمانی DevTools را از نو تنظیم می‌کنند و کنار گذاشته می‌شوند.

کدگذاری طول اجرا

سلول‌های یکسان در یک span از نوع %c ادغام می‌شوند. spanها از نویسه‌های خط جدید عبور می‌کنند و رشته‌های CSS به‌صورت اشتراکی ذخیره می‌شوند.

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

جزئیات Chromium

  • نویسهٔ % به‌شکل %% گریز داده می‌شود.
  • به URLها و متن path:line یک ⁦word joiner⁩ اضافه می‌شود تا DevTools سبک آن‌ها را تغییر ندهد.
  • spanها فقط از ویژگی‌های غیراختصاری CSS استفاده می‌کنند. DevTools هر ویژگی بسط‌یافته را روی هر خط کپی می‌کند.
  • spanها طوری تنظیم می‌شوند که پس‌زمینه‌ها بدون شکاف کنار هم قرار بگیرند.

⁦Firefox⁩ و Safari

⁦Chromium⁩ هر خط از یک span از نوع %c را به‌شکل یک بلوک درون‌خطی چیدمان می‌کند. Firefox و Safari ساختار درون‌خطی spanها را حفظ می‌کنند، بنابراین حاشیه‌های عمودی را نادیده می‌گیرند و ردیف‌های بلند را می‌شکنند. CssConsoleDriver مرورگر را با بررسی قابلیت‌های CSS تشخیص می‌دهد و برای این دو کنسول، ارتفاع خط را بدون حاشیه روی 14 px تنظیم می‌کند، با text-wrap-mode: nowrap شکستن خطوط را غیرفعال می‌کند و با یک پردهٔ line-height: 100vh فریم‌های قبلی را از دید خارج می‌کند. اندازه‌گیری متناسب با کنسول، برای ستون پیوند منبع در Firefox جا باقی می‌گذارد. Safari قلم Menlo را در ابتدای فهرست قلم‌ها قرار می‌دهد، زیرا صفحه‌های آن نمی‌توانند از قلم ⁦SF Mono⁩ نصب‌شده به‌دست کاربر استفاده کنند که ⁦Web Inspector⁩ ممکن است با آن ترسیم کند. برای انتخاب کنسول به‌دست خودتان، آرگومان browser را به createConsoleRoot بدهید.

بنچمارک‌ها

فایل packages/core/test/perf.test.ts روی یک داشبورد متراکم 100×32، میانگین 1,000 فریم (⁦Apple M5 Pro⁩، ⁦Bun 1.4.4⁩):

فریمزمانspanهای %c
بازترسیم کامل (چیدمان، ترسیم، کدگذاری)0.163 ms149
ویرایش یک ردیف0.011 ms149
بیکار0.000 ms0

صفحهٔ وضعیت همین خط پردازش را در مرورگر شما اجرا می‌کند. هنگام اجرای یک نمونه از Playground، دستور text.stats() را در DevTools اجرا کنید.

ویرایش این صفحه در GitHub