perf(terminal): scan synchronized markers in linear work (#23015)

This commit is contained in:
Neil
2026-09-26 12:53:14 -07:00
committed by GitHub
parent 1fc0bfe46d
commit 89d4dd8952
2 changed files with 92 additions and 9 deletions
@@ -0,0 +1,80 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import {
scanSynchronizedForegroundOutput,
SYNCHRONIZED_OUTPUT_START_SEQUENCE as start,
SYNCHRONIZED_OUTPUT_END_SEQUENCE as end
} from './foreground-output-scan'
afterEach(() => vi.restoreAllMocks())
describe('foreground synchronized output scan', () => {
it.each([start, end])('bounds searched characters for a flood of %j markers', (marker) => {
const data = marker.repeat(8192)
const originalIndexOf = String.prototype.indexOf
let searchedCharacters = 0
const spy = vi.spyOn(String.prototype, 'indexOf').mockImplementation(function (
this: string,
search: string,
position = 0
): number {
const result = originalIndexOf.call(this, search, position)
if (this === data && (search === start || search === end)) {
searchedCharacters += (result < 0 ? data.length : result + search.length) - position
}
return result
})
const result = scanSynchronizedForegroundOutput(data, '', false)
spy.mockRestore()
console.info(JSON.stringify({ markers: 8192, chars: data.length, searchedCharacters }))
expect(result).toEqual({
started: marker === start,
ended: marker === end,
active: marker === start,
markerTail: data.slice(-7)
})
expect(searchedCharacters).toBeLessThanOrEqual(data.length * 2)
})
it('preserves the last marker and records both transitions in the current chunk', () => {
expect(scanSynchronizedForegroundOutput(`${end}paint${start}`, '', true)).toEqual({
started: true,
ended: true,
active: true,
markerTail: start.slice(1)
})
expect(scanSynchronizedForegroundOutput(`${start}paint${end}`, '', false)).toEqual({
started: true,
ended: true,
active: false,
markerTail: end.slice(1)
})
})
it.each([start, end])('recognizes %j at every socket split', (marker) => {
for (let split = 1; split < marker.length; split++) {
const first = scanSynchronizedForegroundOutput(marker.slice(0, split), '', marker === end)
const second = scanSynchronizedForegroundOutput(
marker.slice(split),
first.markerTail,
first.active
)
expect(second).toEqual({
started: marker === start,
ended: marker === end,
active: marker === start,
markerTail: marker.slice(1)
})
}
})
it('leaves the latch unchanged for empty output and malformed lookalikes', () => {
for (const data of ['', 'ordinary output', '\x1b[?2026x'.repeat(2048)]) {
expect(scanSynchronizedForegroundOutput(data, '', true)).toEqual({
started: false,
ended: false,
active: true,
markerTail: data.slice(-7)
})
}
})
})
@@ -58,27 +58,30 @@ export function scanSynchronizedForegroundOutput(
let active = wasActive
let started = false
let ended = false
let offset = 0
let startIndex = scanData.indexOf(SYNCHRONIZED_OUTPUT_START_SEQUENCE)
let endIndex = scanData.indexOf(SYNCHRONIZED_OUTPUT_END_SEQUENCE)
while (offset < scanData.length) {
const startIndex = scanData.indexOf(SYNCHRONIZED_OUTPUT_START_SEQUENCE, offset)
const endIndex = scanData.indexOf(SYNCHRONIZED_OUTPUT_END_SEQUENCE, offset)
if (startIndex === -1 && endIndex === -1) {
break
}
// Each marker search advances independently, so a missing counterpart is scanned only once.
while (startIndex !== -1 || endIndex !== -1) {
if (endIndex !== -1 && (startIndex === -1 || endIndex < startIndex)) {
active = false
if (endIndex + SYNCHRONIZED_OUTPUT_END_SEQUENCE.length > currentChunkStartIndex) {
ended = true
}
offset = endIndex + SYNCHRONIZED_OUTPUT_END_SEQUENCE.length
endIndex = scanData.indexOf(
SYNCHRONIZED_OUTPUT_END_SEQUENCE,
endIndex + SYNCHRONIZED_OUTPUT_END_SEQUENCE.length
)
continue
}
active = true
if (startIndex + SYNCHRONIZED_OUTPUT_START_SEQUENCE.length > currentChunkStartIndex) {
started = true
}
offset = startIndex + SYNCHRONIZED_OUTPUT_START_SEQUENCE.length
startIndex = scanData.indexOf(
SYNCHRONIZED_OUTPUT_START_SEQUENCE,
startIndex + SYNCHRONIZED_OUTPUT_START_SEQUENCE.length
)
}
return {