mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 08:59:40 +02:00
perf(i18n): an xterm row record is decided by its rows container, once
xterm's DOM renderer rewrites its rows (`.xterm-rows > div`) on every frame a pane changes, and with a grid of tiles that is every record the i18n observer gets (about 4,600 a second for six printing tiles, all of them row rewrites). Each paid one closest() over the whole skip selector list (the per-record skip of21beacf7, which stays). Every row of one terminal shares its parent, so that parent's own shouldSkip() verdict is now kept once it says skip: same verdict, one closest() per terminal instead of one per record. A rows container outside any skipped surface keeps the full check, so nothing that was translated stops being translated. Measured (6 printing tiles, 30 s profiles, n=3 interleaved A/B, load 5.8 to 9.5, equivalent class-check variant): observer 391 to 445 ms -> 47 to 52 ms per 30 s in English, 473 -> 58 ms in zh-CN; main-thread script time -0.35 s per 30 s (-14%). Frame share unchanged within noise. Live, this code (6 printing tiles, 30 s profiles, interleaved against the file at00440c02, load 4.4 to 6.6): observer 417 to 430 ms -> 56 to 58 ms per 30 s; script time 2.63 to 2.79 s -> 2.24 s in the undisturbed window. The other window of this code was disturbed by CPU contention on the box (every rendering cost 3 to 4 times higher, xterm's own included, 351 frames in 30 s) and is not counted; its observer time was 56 ms all the same. Test: 60 row rewrites in a terminal cost one closest(), the rows stay untranslated, and a stray `.xterm-rows` outside any skip surface is still translated (the verdict closest() gives); mutation-checked both ways. Scope: PR 2 (i18n, on top of21beacf7). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+18
-1
@@ -1142,6 +1142,23 @@
|
||||
return !element || Boolean(element.closest(SKIP_SELECTOR));
|
||||
}
|
||||
|
||||
// xterm's DOM renderer rewrites its rows (`.xterm-rows > div`) on every frame
|
||||
// a pane changes: thousands of mutation records a second with a grid of tiles,
|
||||
// each paying a closest() over the whole skip list. All rows of one terminal
|
||||
// share that parent, so its own shouldSkip() verdict is kept once it says
|
||||
// skip; a skip verdict cannot lapse, since xterm keeps `.xterm-rows` inside
|
||||
// its `.xterm`. A rows container that is not skipped is never kept: its rows
|
||||
// go through the full check below like any other node.
|
||||
const skippedRows = new WeakSet();
|
||||
function isSkippedRow(node) {
|
||||
const rows = node.parentNode;
|
||||
if (!rows?.classList?.contains('xterm-rows')) return false;
|
||||
if (skippedRows.has(rows)) return true;
|
||||
if (!shouldSkip(rows)) return false;
|
||||
skippedRows.add(rows);
|
||||
return true;
|
||||
}
|
||||
|
||||
function shouldSkipText(node) {
|
||||
const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
||||
return shouldSkip(node) || Boolean(element?.closest(USER_TEXT_SELECTOR));
|
||||
@@ -1243,7 +1260,7 @@
|
||||
// check per record instead of one per text node and attribute matters
|
||||
// for xterm's DOM renderer, which replaces rows every frame (the split
|
||||
// pane, every tile of the grid).
|
||||
if (shouldSkip(mutation.target)) continue;
|
||||
if (isSkippedRow(mutation.target) || shouldSkip(mutation.target)) continue;
|
||||
if (mutation.type === 'characterData') translateNode(mutation.target);
|
||||
if (mutation.type === 'attributes') translateAttributes(mutation.target);
|
||||
for (const added of mutation.addedNodes) translateNode(added);
|
||||
|
||||
Reference in New Issue
Block a user