ההקלדה אינה מחשבת סגנון לכל המסמך בכל תו: כלל הבאנר בלי :has() - #53
Conversation
|
אימות על מסמך גדול (165 עמודים, 193 אלף מילים, נוצר לבדיקה): אחרי שהפריסה הראשונית נחה, ההקלדה על הבנייה המתוקנת נותנת חציון 55–75ms מלחיצה עד ציור, p90 כ-100ms, ו-4 long tasks ב-60 הקשות — כמו במסמך של חמישה עמודים — ואפס חישובי סגנון של כל המסמך. הקומיט הנוסף משפר את |
אימות בתוך אוצריא, עם הקשות אמיתיות (
|
המארח: PR לפורק של flutter_inappwebviewמה שנשאר אחרי התיקון כאן — כ‑150ms מהציור ב‑renderer ועד הפיקסלים על המסך — נחקר בצד המארח: Windows.Graphics.Capture מספק פריים בכל טיק של הקומפוזיטור גם כשה‑WebView סטטי, ו‑Flutter צייר ~60fps כל הזמן שתוסף על המסך (~430 ציורים ב‑5 שניות, otzaria.exe ~20% CPU בשקט). התיקון — השוואת הפריים על ה‑GPU ו‑notify ל‑Flutter רק כשפיקסל השתנה — ב‑Otzaria/flutter_inappwebview#19: 18 ציורים ב‑5 שניות (הבהוב הסמן), 0 כשאין שינוי, CPU ~4%. ההשהיה עד המסך לא השתנתה (ספירת ההופים זהה), אבל המכונה כבר לא מבזבזת ליבה על WebView דומם. המדידות נעשו עם |
|
עוד קומיט על הענף (8a74521): מה שנמצא איתו, על המסמך המקורי של הדיווח: התחושה „בטורים זה איטי” לא אושרה — פסקה עם ריצת עיצוב אחת בתוך הטורים מקלידה כמו הכותרת גם בקצב מהיר. מה שכן איטי הוא פסקה עם ריצות עיצוב רבות, שהמנוע מסווג |
|
החלק של המנוע דווח ל-SuperDoc: superdoc/docx-editor#3984 — פסקה עם br/tab/הפניה להערת שוליים בתוך הפסקה כבדה פי שניים להקשה, וההקשות אינן מאוחדות. איכותי בלבד, עם מחולל מסמכי שחזור סינתטיים (gist). החלק של המארח נשאר לסבב הבא. |
8a74521 to
3214450
Compare
תוצאות בדיקת תוספי אוצריאמקור מפרט ה-API: GitHub (זמן אמת)
|
|
תיקון (da9be97): המסקנה „המארח מייקר את ההקשה” נמדדה בזמן שסשן אחר בנה את אוצריא והריץ חבילת בדיקות על אותו מחשב (שתי ליבות). על מחשב שקט — אותה בנייה, אותו מסמך, אותה שורה — העורך עומד בקצב גם בפסקה עם br/tab, כמו ב-Chrome וב-Edge באותו רגע. README עודכן בהתאם (הטריגר: br/tab/הפניה להערת שוליים, לא מספר ריצות), ו-typing-latency-inapp.mjs מדפיס עכשיו את ה-CPU של שאר התהליכים בזמן הפרץ ומזהיר על עומס זר. תגובת תיקון מקבילה נוספה ב-superdoc/docx-editor#3984. |
„לוקח כמה שניות עד שהתו מופיע.” נמדד ב-Chrome על ה-dist, במסמך של חמישה עמודים: על כל הקשה Blink חישב סגנון מחדש לכל עץ המסמך (2,748 אלמנטים, 60–115ms) — 42 פעמים ב-50 הקשות, 53 long tasks. הטריגר: הכלל שהסתיר את באנר edit-rejected דרך `.superdoc__mutation-status:has([data-superdoc-v2-edit-rejected])`. `:has()` שעוגנו בתוך `.superdoc` סימן את `.superdoc` כמושפע מ-:has(), ומאותו רגע כל מוטציה במסמך תזמנה חישוב של תת-העץ כולו. הוכרע בניסוי מבוקר: מחיקת הכלל הזה לבדו בזמן ריצה — 0 חישובים ו-3 long tasks; מחיקת כלל אחר — ללא שינוי. הכלל מסתיר עכשיו את ה-<p> שנושא את התכונה כילד ישיר של העוטף (העוטף הוא height: 0 בלי ריפוד; אין הבדל נראה). שני שערים נגד חזרה: css-hygiene חוסם כל :has() שלא אושר במפורש, ו-check:typing-recalc מקליד תחת trace של ה-renderer וסופר חישובי סגנון בגודל המסמך — אדום על הכלל הישן (112 ב-40 הקשות), ירוק אחרי. scripts/typing-latency-probe.mjs הוא כלי האבחון, כולל --attach לתוסף שרץ בתוך אוצריא. vitest: 185 קבצים, 3,903 בדיקות; typecheck; check:dist; check:typing-recalc.
--open-wait ו---settle: מסמך של 165 עמודים נפתח בכ-14 שניות, ואחרי שהטקסט כבר בעץ המנוע עוד „מסדר את התצוגה” כמה שניות. הקלדה בתוך החלון הזה מודדת את הפתיחה ולא את ההקלדה: נמדדו 42 long tasks ו-p90 של ארבע שניות, ותחת עומס trace המנוע חצה את שעון ה-1000ms שלו והוריד את הציור. עם שהות של 15 שניות אותו מסמך נותן חציון 55–75ms ו-4 long tasks ב-60 הקשות — כמו מסמך של חמישה עמודים, ובלי חישוב סגנון של כל המסמך. --trace-light: בלי invalidationTracking ו-stack, שמכבידים על הדף עצמו. --profile-interval: 250µs היו כבדים על מסמך גדול; 1000µs מספיקים לשיוך.
scripts/typing-latency-inapp.mjs מודד את כל השרשרת בתוך ה-WebView של אוצריא — הקשת מערכת ההפעלה (SendInput) → keydown בדף → ציור (rAF) → שינוי פיקסלים על המסך (--screen) — אחרי לחיצת עכבר אמיתית, כי פוקוס JS אינו פוקוס המקלדת של המערכת. מדפיס נראות ופוקוס לפני שמתחיל: חלון ממוזער או WebView מושהה הופכים את הדף ל-hidden ונראים כהקלדה איטית. ב-typing-latency-probe.mjs, במצב --attach, אין עוד לחיצה סינתטית: בחלון צר השורה חורגת מהחלון והלחיצה נחתה ברצועה על „מסמך חדש”, והמדידה נעשתה במסמך אחר. README: מה נמדד בתוך אוצריא אחרי התיקון, ומה נשאר למארח (שלב הצגת הפריים WebView2 → Windows.Graphics.Capture → Flutter).
…יקסלים לאות עברית הלחיצה האמיתית נוחתת לפי מיקום החלון הנוכחי (אוצריא מזיזה את החלון גם שניות אחרי הפתיחה), נמנעת משורות עם קישורים (קישור פותח ספר ומחליף לשונית), ואם הלשונית התחלפה בכל זאת — חוזרים אליה במקום להיכשל. סף השינוי על המסך ירד ל-60 פיקסלים: אות עברית קטנה משנה כ-100, והבהוב הסמן (~30) מסונן בבסיס הכפול.
…, ומדד ההיערמות בהקלדה מהירה המוטציה הראשונה אחרי הקשה היא שכבת הסמן; התו עצמו מגיע עשרות מילישניות אחריה, ולכן המדד הקודם דיווח „מהר” גם כשלא. הרישום הוא סדרה ומשויך לפי סדר, כך שגם בהקלדה מהירה כל תו מוצמד להקשה שלו, ומודפס כמה אחרי ההקשה האחרונה הטקסט מתיישב. --target בוחר כותרת/טור/שורה לפי טקסט. ב-README: מה שנמדד תלוי במספר ריצות העיצוב בפסקה ולא בטורים.
… על המארח „המארח מייקר כל הקשה” נמדד בזמן שסשן אחר בנה את אוצריא והריץ חבילת בדיקות על אותו מחשב (שתי ליבות). על מחשב שקט — אותה בנייה, אותו מסמך, אותה שורה — העורך עומד בקצב גם בפסקה עם br/tab, כמו ב-Chrome וב-Edge באותו רגע. הסקריפט מצלם עכשיו TotalProcessorTime של כל התהליכים לפני ואחרי הפרץ, מדפיס „תהליכים אחרים” עם השלושה הכבדים, ומזהיר כשהעומס הזר גדול. README: הטריגר הוא br/tab/הפניה להערת שוליים (לא מספר ריצות), והתוצאה על מחשב שקט.
da9be97 to
bb7b631
Compare
מה קרה
„כשאני מקליד, לוקח כמה שניות עד שהתו מופיע.”
נמדד ב-Chrome על ה-
distהארוז, במסמך אמיתי של חמישה עמודים: על כל הקשה הדפדפן חישב סגנון מחדש (UpdateLayoutTree) לכל עץ המסמך — 2,748 אלמנטים, 60–115ms לחישוב — 42 פעמים ב-50 הקשות, עם 53 long tasks. במסמך ריק זה לא קרה. על מכונה עמוסה ובתוך ה-WebView של אוצריא זה מה שמצטבר ל„כמה שניות”.סיבת השורש
לא הקוד שרץ בהקלדה (פחות מאחוז מהזמן היה של התוסף) אלא כלל CSS יחיד ב-
src/styles/engine-chrome.css: ההסתרה של באנרedit-rejectedשל המנוע נכתבה כ-:has()שהעוגן שלו יושב בתוך.superdocגורם ל-Blink לסמן את.superdocכמושפע מ-:has(), ומאותו רגע כל הוספה או הסרה של צומת במסמך — כל תו — מתזמנת חישוב סגנון של תת-העץ כולו. ב-trace עםinvalidationTracking: „Affected by :has()” עלDIV.superdoc, „Invalidation set invalidates subtree”.ההכרעה הייתה ניסוי מבוקר על אותו מסמך, בזמן ריצה, לפני ההקלדה:
.editor-stack__host--pending):has()שברצועההתיקון
הכלל מסתיר את ה-
<p>שנושא את התכונה כילד ישיר של העוטף, בלי:has():העוטף (
SuperDoc.vue) הואheight: 0בלי ריפוד ורקע, ולכן אין הבדל נראה. העיגון הסמנטי בתכונה נשמר.מה מונע חזרה
tests/unit/css-hygiene.test.ts: כל:has()בגיליונות ובבלוקי<style>חייב להופיע ברשימה מאושרת עם נימוק. הרשימה מחזיקה כלל אחד (ברצועה, מחוץ לעץ המסמך — נמדד כבלתי מזיק), והבדיקה נופלת גם אם כלל מאושר נעלם.npm run check:typing-recalc(scripts/qa/typing-style-recalc-qa.mjs): בונה מסמך של ארבעה עמודים דרך ה-Document API, מקליד 40 תווים תחת trace של ה-renderer (חיבור CDP שני, כיTracing.dataCollectedהוא אירוע), וסופר חישובי סגנון של ≥1,000 אלמנטים. מוטציה נמדדה: על ה-dist הישן — 112 חישובים כאלה (1,716ms) → אדום; אחרי התיקון — 0 → ירוק. נוסף ל-verify:qa.tests/contract/engine-edit-rejected-banner.test.tsנועל את הצורה: בלי:has(),>בין העוטף לתכונה, וה-<p>אכן ילד ישיר באריזה.כלי אבחון
scripts/typing-latency-probe.mjs: זמן מלחיצה עד ציור, long tasks, הודעות קונסולה וקריאות למאחז לכל הקשה;--docx,--tab,--drop-css <regex>(הניסוי שלמעלה),--trace, ו---attach <port>לתוסף שרץ בתוך אוצריא (אחרי הרצה עםWEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=<port>). מתועד ב-README, „איטיות בהקלדה”.מה לא נשלח למעלה
גיליון המנוע (
@superdoc/docx-engine, קנייני) גם משתמש ב-:has(), וזה מה שהופך:has()בצד המארח למסוכן. בלי הכלל שלנו התופעה אינה מופיעה, ולכן ההגנה כאן. הרישיון של המנוע אוסר לפרסם מדידות שלו; נרשם איכותית ב-docs/engine-gaps.md.בדיקות שרצו
npm run typecheck— עברnpm test— 185 קבצים, 3,903 בדיקות, כולן עברוnpm run build+npm run check:dist— עברnpm run check:typing-recalc— ירוק על הבנייה הזאת, אדום על הבנייה שלפני התיקוןscripts/typing-latency-probe.mjsעל המסמך שדווח: long tasks בזמן הקלדה 53 → 2