מנוע Turbolog

איך פריימים מקודדים בקידוד אורך ריצה לקריאת console.log אחת, וגם CellBuffer, פרטי Chromium ומבחני ביצועים.

⁦Turbolog⁩ הופך כל commit של 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
ציור מחדש מלא (layout, ציור, קידוד)0.163 ms149
עריכת שורה אחת0.011 ms149
מצב סרק0.000 ms0

עמוד הסטטוס מריץ את אותה שרשרת עיבוד בדפדפן. יש להריץ את text.stats() ב-DevTools בזמן שהדגמה מתוך ה-Playground פועלת.

עריכת הדף ב-GitHub