--- a/apps/mobile/src/features/review/shikiReviewHighlighter.ts +++ b/apps/mobile/src/features/review/shikiReviewHighlighter.ts @@ -216,6 +216,35 @@ function joinPatchLines(lines: ReadonlyArray): string { return lines.map(stripTrailingNewline).join("\n"); +} + +// DIAGNOSTIC BUILD ONLY (never shipped, never in a prod A/B): records each JS slice of highlightLines +// (work since the last resume, wait inside the yield) and logs one summary when the file finishes. +type __T3DiagHl = { start: number; startDate: number; resumedAt: number; batches: number; slices: string[] }; +function __t3diagHlStart(): __T3DiagHl { + const now = performance.now(); + return { start: now, startDate: Date.now(), resumedAt: now, batches: 0, slices: [] }; +} +async function __t3diagHlYield(diag: __T3DiagHl, yieldFn: () => Promise): Promise { + const before = performance.now(); + await yieldFn(); + const after = performance.now(); + diag.slices.push(`${(before - diag.resumedAt).toFixed(1)}/${(after - before).toFixed(1)}/${diag.batches}`); + diag.batches = 0; + diag.resumedAt = after; +} +function __t3diagHlEnd(diag: __T3DiagHl, lines: number, chars: number): void { + const end = performance.now(); + diag.slices.push(`${(end - diag.resumedAt).toFixed(1)}/end/${diag.batches}`); + const work = diag.slices.map((s) => Number(s.split("/")[0])); + const waits = diag.slices.map((s) => s.split("/")[1]).filter((w) => w !== "end").map(Number); + const sum = (xs: number[]) => xs.reduce((a, b) => a + b, 0); + console.log( + `__t3diag hl summary lines=${lines} chars=${chars} slices=${diag.slices.length} total=${(end - diag.start).toFixed(1)}ms totalDate=${Date.now() - diag.startDate}ms work=${sum(work).toFixed(1)} waits=${sum(waits).toFixed(1)} maxWork=${Math.max(...work).toFixed(1)} maxWait=${waits.length ? Math.max(...waits).toFixed(1) : 0}`, + ); + for (let i = 0; i < diag.slices.length; i += 20) { + console.log(`__t3diag hl slices[${i}] ${diag.slices.slice(i, i + 20).join(" ")}`); + } } function waitForNextFrame(): Promise { @@ -517,6 +546,7 @@ const highlighter = await getHighlighter(); const sourceLines = code.split("\n"); + const __t3diag = __t3diagHlStart(); const highlightedLines: Array> = []; // Batches resume from the previous batch's grammar state, so a comment or // template string that spans a batch boundary keeps its colors. @@ -545,7 +575,8 @@ end += 1; } - const tokenLines = highlighter.codeToTokensBase(sourceLines.slice(start, end).join("\n"), { + __t3diag.batches += 1; + const tokenLines = highlighter.codeToTokensBase(sourceLines.slice(start, end).join("\n"), { lang: language, theme, grammarState, @@ -560,11 +591,12 @@ start < sourceLines.length && performance.now() - sliceStartedAt >= REVIEW_HIGHLIGHT_YIELD_AFTER_MS ) { - await waitForNextFrame(); + await __t3diagHlYield(__t3diag, waitForNextFrame); sliceStartedAt = performance.now(); } } + __t3diagHlEnd(__t3diag, sourceLines.length, code.length); return highlightedLines; }