perf(terminal): scan output frames by code unit, not per code point

iterateTerminalOutputFrameChunks walked `for (const part of data)`, materializing
a 1-2 character string per code point and calling terminalStreamByteLength on
each, while accumulating the frame text with `chunk += part`.

The accumulator was never needed: `chunk` only ever reconstructs the contiguous
substring data[chunkStart..end), and `startSeq + chunkStartOffset + chunk.length`
collapses algebraically to `startSeq + end`. Track two integer offsets and emit
data.slice(chunkStart, end) instead, computing UTF-8 width inline from charCodeAt.

Also short-circuits the cap gate on UTF-16 length before measuring UTF-8 bytes,
which is sound because UTF-8 length is never below UTF-16 length.

2.4-6.1x across payload shapes, stable across reruns. This runs per terminal
output batch and per snapshot chunk.

Extracted to its own module along a real seam (the chunk-emission concern plus
its two types and cap gate); methods/terminal.ts shrinks by 85 lines. No
max-lines suppression added and the baseline is untouched.

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Neil
2026-07-27 13:07:38 -07:00
co-authored by Orca
parent cd05f2ff93
commit 0944fdbef9
4 changed files with 932 additions and 91 deletions
@@ -0,0 +1,347 @@
#!/usr/bin/env node
// Benchmark: iterateTerminalOutputFrameChunks, which every byte of remote terminal
// output passes through on its way to a mobile/remote-desktop multiplex stream.
//
// The pre-fix loop was `for (const part of data)`: V8 materializes a fresh 1-2 code
// unit string per code point, then measureClipboardTextByteLength re-walked that
// string through codePointAt to get its UTF-8 width, and the chunk was rebuilt with
// `chunk += part`. The gate in front of it (terminalStreamByteLengthExceeds) ran the
// same per-code-point walk over the whole payload a second time.
//
// The fix: one charCodeAt scan computing the UTF-8 width inline with no per-code-point
// string, chunk text taken as data.slice(chunkStart, end), and a gate of
// `data.length > CHUNK || Buffer.byteLength(data, 'utf8') > CHUNK` -- sound because a
// string's UTF-8 length is never below its UTF-16 length.
//
// BOTH arms run the complete production path, encodeTerminalStreamText included, and
// their emitted frames (base64 + seq + opcode) are compared before any timing, so an
// arm that split differently or renumbered a seq cannot be reported as a win.
import { spawnSync } from 'node:child_process'
import { existsSync, readFileSync } from 'node:fs'
import nodeModule from 'node:module'
import { performance } from 'node:perf_hooks'
import { fileURLToPath } from 'node:url'
// terminal-stream-protocol.ts declares a TS enum, which Node's default strip-only
// loader rejects; re-exec once with type transformation rather than re-modelling
// the opcodes here (a hand copy could drift from the wire contract).
if (!process.execArgv.includes('--experimental-transform-types')) {
const result = spawnSync(
process.execPath,
['--experimental-transform-types', '--no-warnings', import.meta.filename],
{ stdio: 'inherit' }
)
process.exit(result.status ?? 1)
}
// The app's TS sources import siblings without an extension; Node's ESM resolver needs it.
nodeModule.registerHooks({
resolve(specifier, context, nextResolve) {
if (specifier.startsWith('.') && !/\.[cm]?[jt]s$/.test(specifier) && context.parentURL) {
const candidate = new URL(`${specifier}.ts`, context.parentURL)
if (existsSync(fileURLToPath(candidate))) {
return { url: candidate.href, shortCircuit: true }
}
}
return nextResolve(specifier, context)
}
})
const ITERATIONS = Number(process.env.ORCA_FRAME_CHUNK_BENCH_ITERATIONS ?? '40')
const WARMUP = Number(process.env.ORCA_FRAME_CHUNK_BENCH_WARMUP ?? '8')
const ROUNDS = Number(process.env.ORCA_FRAME_CHUNK_BENCH_ROUNDS ?? '6')
for (const [name, value] of [
['ORCA_FRAME_CHUNK_BENCH_ITERATIONS', ITERATIONS],
['ORCA_FRAME_CHUNK_BENCH_WARMUP', WARMUP],
['ORCA_FRAME_CHUNK_BENCH_ROUNDS', ROUNDS]
]) {
if (!Number.isSafeInteger(value) || value <= 0) {
throw new Error(`${name} must be a positive integer, received ${value}`)
}
}
if (ROUNDS % 2 !== 0) {
throw new Error(`ORCA_FRAME_CHUNK_BENCH_ROUNDS must be even so each arm leads equally`)
}
const CHUNK_SOURCE = readFileSync(
new URL('../../src/main/runtime/rpc/terminal-output-frame-chunks.ts', import.meta.url),
'utf8'
)
const CLIPBOARD_SOURCE = readFileSync(
new URL('../../src/shared/clipboard-text.ts', import.meta.url),
'utf8'
)
// Why re-read the sources: this benchmark's claim is that the OLD arm paid a
// measureClipboardTextByteLength call per code point and the NEW one pays a single
// Buffer.byteLength gate. Match the CALL form, not a bare word -- a comment naming
// the function would satisfy a substring check.
for (const [source, label, marker] of [
[CHUNK_SOURCE, 'terminal-output-frame-chunks.ts', "Buffer.byteLength(data, 'utf8')"],
[CHUNK_SOURCE, 'terminal-output-frame-chunks.ts', 'text: data.slice(chunkStart, end)'],
[CHUNK_SOURCE, 'terminal-output-frame-chunks.ts', 'data.charCodeAt(index + 1)'],
[CLIPBOARD_SOURCE, 'clipboard-text.ts', 'export function measureClipboardTextByteLength('],
[CLIPBOARD_SOURCE, 'clipboard-text.ts', 'text.codePointAt(index)']
]) {
if (!source.includes(marker)) {
throw new Error(`${label} no longer contains \`${marker}\`; this benchmark is stale`)
}
}
if (CHUNK_SOURCE.includes('for (const part of data)')) {
throw new Error(
'terminal-output-frame-chunks.ts still iterates code points as strings; this benchmark is stale'
)
}
const { TERMINAL_STREAM_CHUNK_BYTES } = await import(
new URL('../../src/shared/terminal-multiplex-flow-control.ts', import.meta.url).href
)
const { measureClipboardTextByteLength } = await import(
new URL('../../src/shared/clipboard-text.ts', import.meta.url).href
)
const { TerminalStreamOpcode, encodeTerminalStreamJson, encodeTerminalStreamText } = await import(
new URL('../../src/shared/terminal-stream-protocol.ts', import.meta.url).href
)
const { iterateTerminalOutputFrameChunks } = await import(
new URL('../../src/main/runtime/rpc/terminal-output-frame-chunks.ts', import.meta.url).href
)
// Pre-fix arm: the exact code that shipped, including the second full walk in the gate.
function* iterateBefore(data, meta) {
const rawLength = meta?.rawLength ?? data.length
if (meta?.transformed || rawLength !== data.length) {
yield {
opcode: TerminalStreamOpcode.OutputSpan,
bytes: encodeTerminalStreamJson({ data, rawLength, transformed: true }),
seq: meta?.seq
}
return
}
if (
!measureClipboardTextByteLength(data, { stopAfterBytes: TERMINAL_STREAM_CHUNK_BYTES })
.exceededLimit
) {
yield { bytes: encodeTerminalStreamText(data), seq: meta?.seq }
return
}
const canPreserveChunkSeq = typeof meta?.seq === 'number' && rawLength === data.length
const shouldDelayFinalSeq = !canPreserveChunkSeq && typeof meta?.seq === 'number'
const startSeq = canPreserveChunkSeq ? meta.seq - rawLength : undefined
let chunk = ''
let chunkBytes = 0
let chunkStartOffset = 0
let offset = 0
let delayedChunk = null
const takeChunk = () => {
if (!chunk) {
return null
}
const chunkSeq = canPreserveChunkSeq ? startSeq + chunkStartOffset + chunk.length : undefined
const current = { text: chunk, seq: chunkSeq }
chunk = ''
chunkBytes = 0
chunkStartOffset = offset
return current
}
for (const part of data) {
const partBytes = measureClipboardTextByteLength(part).byteLength
if (chunkBytes > 0 && chunkBytes + partBytes > TERMINAL_STREAM_CHUNK_BYTES) {
const nextChunk = takeChunk()
if (nextChunk) {
if (shouldDelayFinalSeq) {
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text) }
}
delayedChunk = nextChunk
} else {
yield { bytes: encodeTerminalStreamText(nextChunk.text), seq: nextChunk.seq }
}
}
}
chunk += part
chunkBytes += partBytes
offset += part.length
}
const finalChunk = takeChunk()
if (shouldDelayFinalSeq) {
if (finalChunk) {
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text) }
}
delayedChunk = finalChunk
}
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text), seq: meta.seq }
}
return
}
if (finalChunk) {
yield { bytes: encodeTerminalStreamText(finalChunk.text), seq: finalChunk.seq }
}
}
// The multiplex stream consumes every frame's bytes/seq/opcode; charge both arms for it.
let frameChecksum = 0
function drain(iterate, data, meta) {
let frames = 0
let bytes = 0
let seqSum = 0
for (const frame of iterate(data, meta)) {
frames += 1
bytes += frame.bytes.byteLength
seqSum += frame.seq ?? 0
}
frameChecksum = Math.imul(frameChecksum ^ (frames + bytes + seqSum), 16777619) >>> 0
return frames
}
function describeFrames(iterate, data, meta) {
const shapes = []
for (const frame of iterate(data, meta)) {
shapes.push(
`${Buffer.from(frame.bytes).toString('base64')}|${frame.seq ?? 'u'}|${frame.opcode ?? 'u'}`
)
}
return shapes.join('\n')
}
const SURROGATE_PAIR = '\u{1f600}'
const LONE_HIGH = '\ud83d'
function repeatTo(unit, codeUnits) {
let out = ''
while (out.length < codeUnits) {
out += unit
}
return out.slice(0, out.length - (out.length % unit.length))
}
// A realistic agent-TUI line: SGR runs, a wide glyph, a currency sign, an emoji.
const TUI_LINE =
'\u001b[35m\u273b Thinking\u001b[0m about the \u20ac plan \u{1f600} 42 passed, 0 failed\r\n'
const fixtures = [
{
label: 'ascii 4KiB (typical batch)',
data: 'x'.repeat(4 * 1024),
meta: (data) => ({ seq: 5_000_000, rawLength: data.length })
},
{
label: `ascii ${TERMINAL_STREAM_CHUNK_BYTES}B (at cap)`,
data: 'x'.repeat(TERMINAL_STREAM_CHUNK_BYTES),
meta: (data) => ({ seq: 5_000_000, rawLength: data.length })
},
{
label: 'ascii 64KiB (batch cap, 2 chunks)',
data: 'x'.repeat(64 * 1024),
meta: (data) => ({ seq: 5_000_000, rawLength: data.length })
},
{
label: 'mixed TUI 64KiB (2 chunks)',
data: repeatTo(TUI_LINE, 64 * 1024),
meta: (data) => ({ seq: 5_000_000, rawLength: data.length })
},
{
// seq without an explicit rawLength: the batcher's ordinary shape.
label: 'mixed TUI 64KiB (implicit raw)',
data: repeatTo(TUI_LINE, 64 * 1024),
meta: () => ({ seq: 5_000_000 })
},
{
label: 'emoji 64KiB (4-byte, 2 chunks)',
data: repeatTo(SURROGATE_PAIR, 32 * 1024),
meta: (data) => ({ seq: 5_000_000, rawLength: data.length })
},
{
label: 'lone surrogates 64KiB',
data: repeatTo(LONE_HIGH, 64 * 1024),
meta: (data) => ({ seq: 5_000_000, rawLength: data.length })
},
{
label: 'ascii 512KiB (snapshot chunking)',
data: 'x'.repeat(512 * 1024),
meta: () => undefined
}
]
function median(samples) {
const sorted = [...samples].sort((a, b) => a - b)
const middle = Math.floor(sorted.length / 2)
return sorted.length % 2 === 0 ? (sorted[middle - 1] + sorted[middle]) / 2 : sorted[middle]
}
// Why interleaved with an alternating lead: running one arm's whole batch first lets
// CPU frequency drift correlate with whichever arm is being measured. Elsewhere in this
// effort that alone reported 23.3x for a real 6.7x.
function measureInterleaved(data, meta) {
for (let index = 0; index < WARMUP; index += 1) {
drain(iterateBefore, data, meta)
drain(iterateTerminalOutputFrameChunks, data, meta)
}
const beforeSamples = []
const afterSamples = []
for (let round = 0; round < ROUNDS; round += 1) {
const runBefore = () => {
const start = performance.now()
for (let index = 0; index < ITERATIONS; index += 1) {
drain(iterateBefore, data, meta)
}
beforeSamples.push((performance.now() - start) / ITERATIONS)
}
const runAfter = () => {
const start = performance.now()
for (let index = 0; index < ITERATIONS; index += 1) {
drain(iterateTerminalOutputFrameChunks, data, meta)
}
afterSamples.push((performance.now() - start) / ITERATIONS)
}
if (round % 2 === 0) {
runBefore()
runAfter()
} else {
runAfter()
runBefore()
}
}
return { beforeMs: median(beforeSamples), afterMs: median(afterSamples) }
}
const pad = (value, width) => String(value).padStart(width)
console.log('iterateTerminalOutputFrameChunks, per flushed batch. Lower is better.')
console.log(
`iterations=${ITERATIONS} warmup=${WARMUP} rounds=${ROUNDS} (alternating lead, per-arm median)`
)
console.log(
`${pad('fixture', 34)} ${pad('frames', 7)} ${pad('per-part', 11)} ${pad('scanned', 11)} ${pad('speedup', 9)}`
)
let comparedFixtures = 0
for (const fixture of fixtures) {
const meta = fixture.meta(fixture.data)
const before = describeFrames(iterateBefore, fixture.data, meta)
const after = describeFrames(iterateTerminalOutputFrameChunks, fixture.data, meta)
if (before !== after) {
throw new Error(`frames differ for ${fixture.label}`)
}
const frames = before.split('\n').length
// Guard against a fixture that never reaches the chunking loop; then both arms would
// just be measuring the gate and the comparison above would prove nothing about it.
if (fixture.data.length > TERMINAL_STREAM_CHUNK_BYTES && frames < 2) {
throw new Error(`${fixture.label} never split; fixture does not exercise the chunk loop`)
}
comparedFixtures += 1
const { beforeMs, afterMs } = measureInterleaved(fixture.data, meta)
console.log(
`${pad(fixture.label, 34)} ${pad(frames, 7)} ${pad(`${beforeMs.toFixed(3)} ms`, 11)} ${pad(`${afterMs.toFixed(3)} ms`, 11)} ${pad(`${(beforeMs / afterMs).toFixed(1)}x`, 9)}`
)
}
console.log(
`\nvalidated=${comparedFixtures} fixtures frame-identical before timing, checksum=${frameChecksum >>> 0}`
)
console.log(
'Every byte of remote terminal output crosses this function; the batcher flushes at\nTERMINAL_OUTPUT_BATCH_MAX_BYTES (64 KiB) or every 5 ms, so a busy remote agent pane\nruns it tens of times a second per subscribed stream.'
)
+6 -91
View File
@@ -17,6 +17,11 @@ import {
encodeTerminalStreamText,
type TerminalStreamFrame
} from '../../../../shared/terminal-stream-protocol'
import {
iterateTerminalOutputFrameChunks,
type TerminalOutputFrameChunk,
type TerminalOutputMeta
} from '../terminal-output-frame-chunks'
import { TERMINAL_PANE_SPLIT_SOURCES } from '../../../../shared/feature-education-telemetry'
import type { TerminalOscLinkRange } from '../../../../shared/terminal-osc-link-ranges'
import {
@@ -49,8 +54,7 @@ import {
TERMINAL_MULTIPLEX_ACK_TOTAL_MAX_WINDOW_BYTES,
TERMINAL_MULTIPLEX_MAX_STREAMS_PER_CONNECTION,
TERMINAL_MULTIPLEX_PENDING_MAX_BYTES,
TERMINAL_OUTPUT_BATCH_MAX_BYTES,
TERMINAL_STREAM_CHUNK_BYTES
TERMINAL_OUTPUT_BATCH_MAX_BYTES
} from '../../../../shared/terminal-multiplex-flow-control'
import { drainTerminalMultiplexRoundRobin } from '../terminal-multiplex-round-robin'
@@ -139,19 +143,6 @@ type TerminalOutputChunk = {
meta?: TerminalOutputMeta
}
type TerminalOutputMeta = {
seq?: number
rawLength?: number
transformed?: boolean
cwd?: string
}
type TerminalOutputFrameChunk = {
bytes: Uint8Array<ArrayBufferLike>
seq?: number
opcode?: TerminalStreamOpcode
}
function createTerminalOutputBatcher(onFlush: (data: string, meta?: TerminalOutputMeta) => void): {
push: (data: string, meta?: TerminalOutputMeta) => void
flush: () => void
@@ -240,82 +231,6 @@ function createTerminalOutputBatcher(onFlush: (data: string, meta?: TerminalOutp
}
}
function* iterateTerminalOutputFrameChunks(
data: string,
meta?: TerminalOutputMeta
): Generator<TerminalOutputFrameChunk> {
const rawLength = meta?.rawLength ?? data.length
if (meta?.transformed || rawLength !== data.length) {
yield {
opcode: TerminalStreamOpcode.OutputSpan,
bytes: encodeTerminalStreamJson({ data, rawLength, transformed: true }),
seq: meta?.seq
}
return
}
if (!terminalStreamByteLengthExceeds(data, TERMINAL_STREAM_CHUNK_BYTES)) {
yield { bytes: encodeTerminalStreamText(data), seq: meta?.seq }
return
}
const canPreserveChunkSeq = typeof meta?.seq === 'number' && rawLength === data.length
const shouldDelayFinalSeq = !canPreserveChunkSeq && typeof meta?.seq === 'number'
const startSeq = canPreserveChunkSeq ? meta.seq! - rawLength : undefined
let chunk = ''
let chunkBytes = 0
let chunkStartOffset = 0
let offset = 0
let delayedChunk: { text: string; seq?: number } | null = null
const takeChunk = (): { text: string; seq?: number } | null => {
if (!chunk) {
return null
}
const chunkSeq = canPreserveChunkSeq ? startSeq! + chunkStartOffset + chunk.length : undefined
const current = { text: chunk, seq: chunkSeq }
chunk = ''
chunkBytes = 0
chunkStartOffset = offset
return current
}
for (const part of data) {
const partBytes = terminalStreamByteLength(part)
if (chunkBytes > 0 && chunkBytes + partBytes > TERMINAL_STREAM_CHUNK_BYTES) {
const nextChunk = takeChunk()
if (nextChunk) {
if (shouldDelayFinalSeq) {
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text) }
}
delayedChunk = nextChunk
} else {
yield { bytes: encodeTerminalStreamText(nextChunk.text), seq: nextChunk.seq }
}
}
}
chunk += part
chunkBytes += partBytes
offset += part.length
}
const finalChunk = takeChunk()
if (shouldDelayFinalSeq) {
// Why: only the final frame can safely carry the high-water mark when rawLength can't map back to UTF-16 offsets.
if (finalChunk) {
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text) }
}
delayedChunk = finalChunk
}
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text), seq: meta.seq }
}
return
}
if (finalChunk) {
yield { bytes: encodeTerminalStreamText(finalChunk.text), seq: finalChunk.seq }
}
}
function isTerminalInputLockedForClient(
runtime: OrcaRuntimeService,
ptyId: string,
@@ -0,0 +1,467 @@
import { describe, expect, it } from 'vitest'
import {
TerminalStreamOpcode,
encodeTerminalStreamJson,
encodeTerminalStreamText
} from '../../../shared/terminal-stream-protocol'
import { TERMINAL_STREAM_CHUNK_BYTES } from '../../../shared/terminal-multiplex-flow-control'
import { measureClipboardTextByteLength } from '../../../shared/clipboard-text'
import {
iterateTerminalOutputFrameChunks,
type TerminalOutputFrameChunk,
type TerminalOutputMeta
} from './terminal-output-frame-chunks'
// Byte-for-byte reference: the pre-optimization implementation, copied verbatim.
// It accumulates `chunk += part` over `for (const part of data)` and measures each
// code point through the shared clipboard measurer.
function legacyByteLength(data: string): number {
return measureClipboardTextByteLength(data).byteLength
}
function legacyByteLengthExceeds(data: string, maxBytes: number): boolean {
return measureClipboardTextByteLength(data, { stopAfterBytes: maxBytes }).exceededLimit
}
function* legacyIterateTerminalOutputFrameChunks(
data: string,
meta?: TerminalOutputMeta
): Generator<TerminalOutputFrameChunk> {
const rawLength = meta?.rawLength ?? data.length
if (meta?.transformed || rawLength !== data.length) {
yield {
opcode: TerminalStreamOpcode.OutputSpan,
bytes: encodeTerminalStreamJson({ data, rawLength, transformed: true }),
seq: meta?.seq
}
return
}
if (!legacyByteLengthExceeds(data, TERMINAL_STREAM_CHUNK_BYTES)) {
yield { bytes: encodeTerminalStreamText(data), seq: meta?.seq }
return
}
const canPreserveChunkSeq = typeof meta?.seq === 'number' && rawLength === data.length
const shouldDelayFinalSeq = !canPreserveChunkSeq && typeof meta?.seq === 'number'
const startSeq = canPreserveChunkSeq ? meta.seq! - rawLength : undefined
let chunk = ''
let chunkBytes = 0
let chunkStartOffset = 0
let offset = 0
let delayedChunk: { text: string; seq?: number } | null = null
const takeChunk = (): { text: string; seq?: number } | null => {
if (!chunk) {
return null
}
const chunkSeq = canPreserveChunkSeq ? startSeq! + chunkStartOffset + chunk.length : undefined
const current = { text: chunk, seq: chunkSeq }
chunk = ''
chunkBytes = 0
chunkStartOffset = offset
return current
}
for (const part of data) {
const partBytes = legacyByteLength(part)
if (chunkBytes > 0 && chunkBytes + partBytes > TERMINAL_STREAM_CHUNK_BYTES) {
const nextChunk = takeChunk()
if (nextChunk) {
if (shouldDelayFinalSeq) {
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text) }
}
delayedChunk = nextChunk
} else {
yield { bytes: encodeTerminalStreamText(nextChunk.text), seq: nextChunk.seq }
}
}
}
chunk += part
chunkBytes += partBytes
offset += part.length
}
const finalChunk = takeChunk()
if (shouldDelayFinalSeq) {
if (finalChunk) {
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text) }
}
delayedChunk = finalChunk
}
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text), seq: meta.seq }
}
return
}
if (finalChunk) {
yield { bytes: encodeTerminalStreamText(finalChunk.text), seq: finalChunk.seq }
}
}
type FrameShape = { base64: string; seq: number | 'undefined'; opcode: number | 'undefined' }
function describeFrames(frames: Iterable<TerminalOutputFrameChunk>): FrameShape[] {
const out: FrameShape[] = []
for (const frame of frames) {
out.push({
base64: Buffer.from(frame.bytes).toString('base64'),
seq: frame.seq ?? 'undefined',
opcode: frame.opcode ?? 'undefined'
})
}
return out
}
function expectEquivalent(data: string, meta: TerminalOutputMeta | undefined, label: string): void {
const legacy = describeFrames(legacyIterateTerminalOutputFrameChunks(data, meta))
const next = describeFrames(iterateTerminalOutputFrameChunks(data, meta))
expect(next, label).toEqual(legacy)
}
const SURROGATE_PAIR = '\u{1f600}'
const LONE_HIGH = '\ud83d'
const LONE_LOW = '\ude00'
// Extremes of both surrogate ranges: U+10000 (D800 DC00) and U+10FFFF (DBFF DFFF).
const FIRST_ASTRAL = '\u{10000}'
const LAST_ASTRAL = '\u{10ffff}'
const SURROGATE_EDGES = [
'\ud800',
'\udbff',
'\udc00',
'\udfff',
FIRST_ASTRAL,
LAST_ASTRAL,
'\udbff\udbff',
'\ud800\udbff',
'\udfff\udc00'
]
// Meta shapes exercised against every fixture: no meta, seq-preserved (rawLength ===
// data.length), the delayed-final-seq path (rawLength !== data.length -> OutputSpan),
// transformed, and cwd-only.
function metaShapesFor(data: string): { label: string; meta: TerminalOutputMeta | undefined }[] {
return [
{ label: 'no-meta', meta: undefined },
{ label: 'seq-only', meta: { seq: 5_000_000 } },
{ label: 'seq+rawLength=len', meta: { seq: 9_000, rawLength: data.length } },
{ label: 'seq+rawLength!=len', meta: { seq: 9_000, rawLength: data.length + 7 } },
{ label: 'rawLength!=len only', meta: { rawLength: data.length + 3 } },
{ label: 'transformed', meta: { seq: 42, rawLength: data.length, transformed: true } },
{ label: 'cwd-only', meta: { cwd: '/home/dev/orca' } },
{ label: 'seq=0', meta: { seq: 0, rawLength: data.length } }
]
}
function sweepAll(data: string, label: string): void {
for (const shape of metaShapesFor(data)) {
expectEquivalent(data, shape.meta, `${label} [${shape.label}]`)
}
}
// A fixture whose seq path is only observable when rawLength maps 1:1 to UTF-16
// offsets; forcing that shape is what makes the algebraic collapse testable.
function seqPreservingMeta(data: string, seq: number): TerminalOutputMeta {
return { seq, rawLength: data.length }
}
function escapeUnits(value: string): string {
const units: string[] = []
for (let index = 0; index < value.length; index += 1) {
units.push(`U+${value.charCodeAt(index).toString(16).toUpperCase()}`)
}
return units.join(' ')
}
function repeatToLength(unit: string, codeUnits: number): string {
let out = ''
while (out.length < codeUnits) {
out += unit
}
return out.slice(0, out.length - (out.length % unit.length))
}
// Deterministic PRNG so a fuzz failure is reproducible from the seed alone.
function makeRandom(seed: number): () => number {
let state = seed >>> 0 || 1
return () => {
state ^= state << 13
state >>>= 0
state ^= state >>> 17
state ^= state << 5
state >>>= 0
return state / 0x1_0000_0000
}
}
const FUZZ_ALPHABET = [
'a',
'z',
'\r',
'\n',
'\u00e9',
'\u20ac',
SURROGATE_PAIR,
LONE_HIGH,
LONE_LOW,
'\u0000',
'\u001b'
]
function randomText(random: () => number, parts: number): string {
let out = ''
for (let index = 0; index < parts; index += 1) {
out += FUZZ_ALPHABET[Math.floor(random() * FUZZ_ALPHABET.length)]
}
return out
}
describe('iterateTerminalOutputFrameChunks equivalence with the pre-optimization loop', () => {
it('matches on the small/no-chunking sizes', () => {
for (const size of [0, 1, 2, 3, 7, 64, 1024, TERMINAL_STREAM_CHUNK_BYTES - 1]) {
sweepAll('a'.repeat(size), `ascii ${size}`)
}
})
it('matches across 1B..200KiB ASCII payloads', () => {
for (const size of [
1,
100,
TERMINAL_STREAM_CHUNK_BYTES,
TERMINAL_STREAM_CHUNK_BYTES + 1,
TERMINAL_STREAM_CHUNK_BYTES * 2,
TERMINAL_STREAM_CHUNK_BYTES * 3 + 17,
100 * 1024,
200 * 1024
]) {
sweepAll('x'.repeat(size), `ascii ${size}`)
}
})
it('matches on multi-byte-only payloads at every UTF-8 width', () => {
// UTF-8 width boundaries: 1|2 at U+0080, 2|3 at U+0800, 3|4 at U+10000.
for (const unit of [
'\u00e9',
'\u20ac',
SURROGATE_PAIR,
'\u0080',
'\u07ff',
'\u0800',
'\uffff'
]) {
for (const codeUnits of [
TERMINAL_STREAM_CHUNK_BYTES / 2,
TERMINAL_STREAM_CHUNK_BYTES,
TERMINAL_STREAM_CHUNK_BYTES + 64,
90 * 1024
]) {
const data = repeatToLength(unit, codeUnits)
sweepAll(data, `unit=${JSON.stringify(unit)} codeUnits=${codeUnits}`)
}
}
})
it('matches with lone surrogates, including a trailing lone high surrogate', () => {
const filler = 'a'.repeat(TERMINAL_STREAM_CHUNK_BYTES + 5)
for (const data of [
LONE_HIGH,
LONE_LOW,
LONE_HIGH + LONE_HIGH,
LONE_LOW + LONE_HIGH,
filler + LONE_HIGH,
filler + LONE_LOW,
LONE_HIGH + filler,
LONE_LOW + filler,
filler + LONE_HIGH + filler,
// Reversed pair: never a valid pair, so both halves must stay 3-byte replacements.
filler + LONE_LOW + LONE_HIGH + filler,
repeatToLength(LONE_HIGH, 60 * 1024),
repeatToLength(LONE_LOW + LONE_HIGH, 60 * 1024)
]) {
sweepAll(data, `lone-surrogate len=${data.length}`)
}
})
it('matches at both ends of both surrogate ranges (U+D800..U+DBFF, U+DC00..U+DFFF)', () => {
const filler = 'a'.repeat(TERMINAL_STREAM_CHUNK_BYTES + 5)
for (const edge of SURROGATE_EDGES) {
for (const data of [
edge,
filler + edge,
edge + filler,
filler + edge + filler,
repeatToLength(edge, 40 * 1024)
]) {
sweepAll(data, `surrogate-edge ${escapeUnits(edge)} len=${data.length}`)
}
// Land the split inside the edge sequence itself.
for (let offset = -4; offset <= 4; offset += 1) {
const data = `${'a'.repeat(TERMINAL_STREAM_CHUNK_BYTES + offset)}${edge}${'b'.repeat(8)}`
expectEquivalent(data, undefined, `surrogate-edge ${escapeUnits(edge)} offset=${offset}`)
expectEquivalent(
data,
seqPreservingMeta(data, 500_000 + data.length),
`surrogate-edge ${escapeUnits(edge)} offset=${offset} seq`
)
}
}
})
it('sweeps a chunk boundary across a surrogate pair at CHUNK-4..CHUNK+4', () => {
for (let offset = -4; offset <= 4; offset += 1) {
const prefixBytes = TERMINAL_STREAM_CHUNK_BYTES + offset
const data = `${'a'.repeat(prefixBytes)}${SURROGATE_PAIR}${'b'.repeat(64)}`
sweepAll(data, `pair boundary offset=${offset}`)
expectEquivalent(
data,
seqPreservingMeta(data, 1_000_000 + data.length),
`pair boundary offset=${offset} seq-preserved`
)
}
})
it('sweeps a chunk boundary across a multi-byte run at CHUNK-4..CHUNK+4', () => {
for (let offset = -4; offset <= 4; offset += 1) {
const prefixBytes = TERMINAL_STREAM_CHUNK_BYTES + offset
// 3-byte run straddling the cap: the split point cannot land mid-code-point.
const data = `${'a'.repeat(prefixBytes)}${'\u20ac'.repeat(32)}${'b'.repeat(16)}`
sweepAll(data, `multibyte boundary offset=${offset}`)
}
})
it('sweeps a chunk boundary across a lone surrogate at CHUNK-4..CHUNK+4', () => {
for (let offset = -4; offset <= 4; offset += 1) {
const prefixBytes = TERMINAL_STREAM_CHUNK_BYTES + offset
for (const lone of [LONE_HIGH, LONE_LOW]) {
const data = `${'a'.repeat(prefixBytes)}${lone}${'b'.repeat(64)}`
sweepAll(data, `lone ${lone === LONE_HIGH ? 'high' : 'low'} boundary offset=${offset}`)
}
// Lone high surrogate as the very last code unit of the payload.
const trailing = `${'a'.repeat(prefixBytes)}${LONE_HIGH}`
sweepAll(trailing, `trailing lone high offset=${offset}`)
}
})
it('sweeps 2-byte and 4-byte code points across a 1-code-unit window at the cap', () => {
for (const unit of ['\u00e9', SURROGATE_PAIR]) {
for (
let pad = TERMINAL_STREAM_CHUNK_BYTES - 6;
pad <= TERMINAL_STREAM_CHUNK_BYTES + 2;
pad += 1
) {
const data = `${'a'.repeat(pad)}${unit.repeat(8)}${'z'.repeat(8)}`
expectEquivalent(data, undefined, `window unit=${unit} pad=${pad}`)
expectEquivalent(
data,
seqPreservingMeta(data, 777 + data.length),
`window unit=${unit} pad=${pad} seq`
)
expectEquivalent(
data,
{ seq: 777, rawLength: data.length + 1 },
`window unit=${unit} pad=${pad} delayed`
)
}
}
})
it('matches on the delayed-final-seq path across many chunk counts', () => {
// rawLength !== data.length routes to OutputSpan; force the multi-chunk delayed
// path by keeping rawLength === data.length but seq present with transformed=false,
// then separately assert the true delayed shape (canPreserveChunkSeq=false).
for (const chunkCount of [1, 2, 3, 5, 9]) {
const data = `${'m'.repeat(TERMINAL_STREAM_CHUNK_BYTES * chunkCount)}${SURROGATE_PAIR}tail`
expectEquivalent(data, { seq: 4242 }, `delayed chunks=${chunkCount} seq-only`)
expectEquivalent(data, { seq: 4242, rawLength: 1 }, `delayed chunks=${chunkCount} raw=1`)
expectEquivalent(data, undefined, `delayed chunks=${chunkCount} no-meta`)
}
})
it('matches on realistic mixed terminal output', () => {
const line = '\u001b[35m\u273b Thinking\u001b[0m about the \u20ac plan \u{1f600} 42 passed\r\n'
for (const repeats of [1, 200, 2000, 6000]) {
const data = line.repeat(repeats)
sweepAll(data, `mixed repeats=${repeats}`)
}
})
it('fuzzes 4000 short random payloads over the surrogate/control alphabet', () => {
const random = makeRandom(0x5eed_1234)
for (let trial = 0; trial < 4000; trial += 1) {
const data = randomText(random, Math.floor(random() * 40))
expectEquivalent(data, undefined, `fuzz-small trial=${trial}`)
expectEquivalent(
data,
{ seq: 31337, rawLength: data.length },
`fuzz-small seq trial=${trial}`
)
}
})
it('fuzzes 800 near-cap payloads whose split point lands in the random region', () => {
const random = makeRandom(0x1234_5eed)
for (let trial = 0; trial < 800; trial += 1) {
const fillerLength = TERMINAL_STREAM_CHUNK_BYTES - 6 + Math.floor(random() * 12)
const data = 'q'.repeat(fillerLength) + randomText(random, 1 + Math.floor(random() * 24))
expectEquivalent(data, undefined, `fuzz-cap trial=${trial}`)
expectEquivalent(data, { seq: 88_888, rawLength: data.length }, `fuzz-cap seq trial=${trial}`)
expectEquivalent(data, { seq: 88_888 }, `fuzz-cap delayed trial=${trial}`)
}
})
it('keeps every emitted frame within the wire cap and reassembles to the input', () => {
const data = `${'a'.repeat(200 * 1024)}${SURROGATE_PAIR.repeat(4096)}${LONE_HIGH}`
const frames = [...iterateTerminalOutputFrameChunks(data, seqPreservingMeta(data, 999_999))]
expect(frames.length).toBeGreaterThan(4)
for (const frame of frames) {
expect(frame.bytes.byteLength).toBeLessThanOrEqual(TERMINAL_STREAM_CHUNK_BYTES)
}
expect(Buffer.concat(frames.map((frame) => Buffer.from(frame.bytes))).toString('utf8')).toBe(
Buffer.from(new TextEncoder().encode(data)).toString('utf8')
)
// Seqs must be strictly increasing and end at the meta high-water mark.
const seqs = frames.map((frame) => frame.seq!)
expect(seqs.every((seq, index) => index === 0 || seq > seqs[index - 1]!)).toBe(true)
expect(seqs.at(-1)).toBe(999_999)
})
it('emits exactly one frame when the payload fits the cap in bytes but not naively', () => {
// 3-byte code points: 16384 code units = 49152 bytes = exactly the cap.
const exact = '\u20ac'.repeat(TERMINAL_STREAM_CHUNK_BYTES / 3)
expect(Buffer.byteLength(exact, 'utf8')).toBe(TERMINAL_STREAM_CHUNK_BYTES)
expect([...iterateTerminalOutputFrameChunks(exact)]).toHaveLength(1)
expect([...legacyIterateTerminalOutputFrameChunks(exact)]).toHaveLength(1)
const overByOne = `${exact}a`
expect([...iterateTerminalOutputFrameChunks(overByOne)].length).toBeGreaterThan(1)
expect([...legacyIterateTerminalOutputFrameChunks(overByOne)].length).toBeGreaterThan(1)
})
// The chunking loop is only reached when rawLength === data.length and transformed
// is falsy, which makes canPreserveChunkSeq === (typeof meta.seq === 'number') and
// therefore shouldDelayFinalSeq unconditionally false. The branch survives here
// (it also survived in the pre-optimization code) purely as defence in depth.
it('never reaches the delayed-final-seq branch for any meta shape', () => {
for (const data of ['', 'a', 'abc', 'x'.repeat(200)]) {
for (const seq of [undefined, 0, 5] as (number | undefined)[]) {
for (const rawDelta of [undefined, 0, 1, -1] as (number | undefined)[]) {
for (const transformed of [undefined, false, true] as (boolean | undefined)[]) {
const meta: TerminalOutputMeta = {}
if (seq !== undefined) {
meta.seq = seq
}
if (rawDelta !== undefined) {
meta.rawLength = data.length + rawDelta
}
if (transformed !== undefined) {
meta.transformed = transformed
}
const rawLength = meta.rawLength ?? data.length
const reachesChunkLoop = !meta.transformed && rawLength === data.length
const canPreserveChunkSeq = typeof meta.seq === 'number' && rawLength === data.length
const shouldDelayFinalSeq = !canPreserveChunkSeq && typeof meta.seq === 'number'
expect(reachesChunkLoop && shouldDelayFinalSeq, JSON.stringify(meta)).toBe(false)
}
}
}
}
})
})
@@ -0,0 +1,112 @@
import {
TerminalStreamOpcode,
encodeTerminalStreamJson,
encodeTerminalStreamText
} from '../../../shared/terminal-stream-protocol'
import { TERMINAL_STREAM_CHUNK_BYTES } from '../../../shared/terminal-multiplex-flow-control'
export type TerminalOutputMeta = {
seq?: number
rawLength?: number
transformed?: boolean
cwd?: string
}
export type TerminalOutputFrameChunk = {
bytes: Uint8Array<ArrayBufferLike>
seq?: number
opcode?: TerminalStreamOpcode
}
// Why: UTF-8 length is never below UTF-16 length, so a code-unit count over the cap already proves the byte count is.
function exceedsTerminalStreamChunkBytes(data: string): boolean {
return (
data.length > TERMINAL_STREAM_CHUNK_BYTES ||
Buffer.byteLength(data, 'utf8') > TERMINAL_STREAM_CHUNK_BYTES
)
}
export function* iterateTerminalOutputFrameChunks(
data: string,
meta?: TerminalOutputMeta
): Generator<TerminalOutputFrameChunk> {
const rawLength = meta?.rawLength ?? data.length
if (meta?.transformed || rawLength !== data.length) {
yield {
opcode: TerminalStreamOpcode.OutputSpan,
bytes: encodeTerminalStreamJson({ data, rawLength, transformed: true }),
seq: meta?.seq
}
return
}
if (!exceedsTerminalStreamChunkBytes(data)) {
yield { bytes: encodeTerminalStreamText(data), seq: meta?.seq }
return
}
const canPreserveChunkSeq = typeof meta?.seq === 'number' && rawLength === data.length
// Unreachable past the OutputSpan branch above (rawLength === data.length there), but kept
// as defence in depth: it is the only shape that can carry a seq the chunk offsets can't map.
const shouldDelayFinalSeq = !canPreserveChunkSeq && typeof meta?.seq === 'number'
const startSeq = canPreserveChunkSeq ? meta.seq! - rawLength : undefined
let chunkStart = 0
let chunkBytes = 0
let delayedChunk: { text: string; seq?: number } | null = null
// Why two offsets instead of an accumulator: the emitted text is always the contiguous
// substring from chunkStart to end, and startSeq + chunkStart + text.length is startSeq + end.
const takeChunk = (end: number): { text: string; seq?: number } => {
const current = {
text: data.slice(chunkStart, end),
seq: canPreserveChunkSeq ? startSeq! + end : undefined
}
chunkStart = end
chunkBytes = 0
return current
}
let index = 0
while (index < data.length) {
const code = data.charCodeAt(index)
let width = 1
let partBytes = 3
if (code < 0x80) {
partBytes = 1
} else if (code < 0x800) {
partBytes = 2
} else if (
code >= 0xd800 &&
code <= 0xdbff &&
// Past the end charCodeAt is NaN, which masks to 0 — a trailing lone surrogate stays 3 bytes.
(data.charCodeAt(index + 1) & 0xfc00) === 0xdc00
) {
partBytes = 4
width = 2
}
// Why chunkBytes > 0: keeps a code point wider than the whole cap in its own frame
// instead of splitting an empty one forever.
if (chunkBytes > 0 && chunkBytes + partBytes > TERMINAL_STREAM_CHUNK_BYTES) {
const nextChunk = takeChunk(index)
if (shouldDelayFinalSeq) {
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text) }
}
delayedChunk = nextChunk
} else {
yield { bytes: encodeTerminalStreamText(nextChunk.text), seq: nextChunk.seq }
}
}
chunkBytes += partBytes
index += width
}
// A split always advances past its boundary, so the tail after the loop is never empty.
const finalChunk = takeChunk(data.length)
if (shouldDelayFinalSeq) {
// Why: only the final frame can safely carry the high-water mark when rawLength can't map back to UTF-16 offsets.
if (delayedChunk) {
yield { bytes: encodeTerminalStreamText(delayedChunk.text) }
}
yield { bytes: encodeTerminalStreamText(finalChunk.text), seq: meta.seq }
return
}
yield { bytes: encodeTerminalStreamText(finalChunk.text), seq: finalChunk.seq }
}