Files
orca/config/scripts/terminal-partial-escape-tail-benchmark.mjs
Neil 4c5077d57a perf(persistence): skip rewriting unchanged terminal scrollback snapshots (#18764)
* perf(terminal): tighten the partial-escape-tail benchmark and equivalence test

* perf(terminal): spell the ESC gate the same way as the sibling ingest gates

* test(terminal): differential-fuzz the ESC-free partial-escape-tail gate against the unguarded fold

* test(terminal): make the escape-tail fuzz exhaustive at symbol depth, and cap the fold expectation

Two review findings on the differential fuzz, both about the test faithfully modelling the
function it guards.

The odometer generated strings by symbol depth but the caller filtered on `chunk.length`, which
is the UTF-16 code-unit count. An astral symbol is two code units, so every depth-4 string
containing one was silently skipped and the corpus was not exhaustive at depth 4 the way the
test name claimed. The generator now yields `{ depth, text }` and the caller filters on depth.
That restores the missing strings and takes the pinned corpus from 516,566 to 593,468 - exactly
the count CodeRabbit derived for the intended corpus.

The pairing assertion in the sibling suite compared the capped `advancePartialEscapeTail`
against an uncapped `extractPartialEscapeTail(pending + chunk)`. It passed only because no
pairing in that corpus crosses MAX_PARTIAL_ESCAPE_TAIL_LENGTH; it would have stopped modelling
the function the moment one did. The cap now lives in the expectation, matching the fuzz
oracle.

Re-verified the fuzz still fails on a wrong guard: mutating the gate to a bracket check fails
all four tests with a `gate diverged` assertion on a lone ESC chunk.

Reported by CodeRabbit and pullfrog on #18748.
2026-09-05 00:34:36 -07:00

89 lines
3.0 KiB
JavaScript

#!/usr/bin/env node
// Times the partial-escape-tail fold that runs once per PTY chunk for every terminal against a
// baseline with the pre-change shape (unconditional concat + per-code-unit walk). Equivalence is
// proven over a corpus first, so the reported speedup cannot come from the gate changing the answer.
import { performance } from 'node:perf_hooks'
import {
advancePartialEscapeTail,
extractPartialEscapeTail,
MAX_PARTIAL_ESCAPE_TAIL_LENGTH
} from '../../src/shared/terminal-partial-escape-tail.ts'
const CHUNK_BYTES = 16 * 1024
const CHUNKS = 640
const ROUNDS = 7
function baselineAdvance(pendingTail, chunk) {
const tail = extractPartialEscapeTail(pendingTail + chunk)
return tail.length > MAX_PARTIAL_ESCAPE_TAIL_LENGTH ? '' : tail
}
const chunkOf = (line) => line.repeat(Math.ceil(CHUNK_BYTES / line.length)).slice(0, CHUNK_BYTES)
const escFreeChunk = chunkOf('[build] compiled src/renderer/src/components/thing.tsx in 12ms\n')
const colouredChunk = chunkOf(
'\x1b[32m[build]\x1b[0m compiled src/renderer/src/components/thing.tsx in 12ms\n'
)
// Every state the scanner can be left in, plus the boundaries the gate must not swallow.
const PIECES = [
'',
'plain output\n',
'\x1b[32mgreen\x1b[0m',
'\x1b[3',
'\x1b]0;title\x07',
'\x1b]0;partial',
'\x1bP dcs payload',
'\x1b',
'\x18',
'\x1a',
'\x1b]8;;https://example.com\x1b\\',
'\x1b]8;;https://example.com\x1b',
'\x1b(B',
'\x1b(',
'\x1b[1;2;3',
escFreeChunk
]
let checked = 0
for (const pending of PIECES.map((piece) => extractPartialEscapeTail(piece))) {
for (const chunk of PIECES) {
const expected = baselineAdvance(pending, chunk)
const actual = advancePartialEscapeTail(pending, chunk)
if (expected !== actual) {
throw new Error(
`gate changed the tracked tail: ${JSON.stringify({ pending, chunk, expected, actual })}`
)
}
checked += 1
}
}
function medianMs(advance, chunk) {
// First sample is the warm-up and is discarded.
const samples = Array.from({ length: ROUNDS + 1 }, () => {
const start = performance.now()
let tail = ''
for (let index = 0; index < CHUNKS; index += 1) {
tail = advance(tail, chunk)
}
return performance.now() - start
})
return samples.slice(1).sort((left, right) => left - right)[Math.floor(ROUNDS / 2)]
}
const megabytes = ((CHUNK_BYTES * CHUNKS) / 1024 / 1024).toFixed(1)
console.log(
`Partial-escape-tail fold: ${CHUNKS} x ${CHUNK_BYTES / 1024} KB chunks (${megabytes} MB), ${checked} equivalence cases verified\n`
)
console.log('| stream shape | before | after | |')
console.log('| --- | --- | --- | --- |')
for (const [label, chunk] of [
['ESC-free (build logs, `cat`, piped output)', escFreeChunk],
['SGR-coloured output (gate does not apply)', colouredChunk]
]) {
const before = medianMs(baselineAdvance, chunk)
const after = medianMs(advancePartialEscapeTail, chunk)
console.log(
`| ${label} | ${before.toFixed(2)} ms | ${after.toFixed(2)} ms | ${(before / after).toFixed(1)}x |`
)
}