revert(terminal): stop pacing latency-sensitive foreground redraws

Dense-SGR pacing was also applied to foreground writes inside the
post-keystroke window. There it traded an unmeasured benefit for two
concrete costs: a macrotask delay before first paint, since the write
became an enqueue plus a zero-delay drain, and up to eight viewport
snapshot/settle cycles where there had been one, because the forced
refresh flag rides every split batch.

The 128 KiB parser burst this pacing exists to bound lives on the
background and drain paths, which keep all of it. Restore the
synchronous write on the latency-sensitive path and pin it with a test.
This commit is contained in:
Neil
2026-09-19 15:19:30 -07:00
parent bf53d28ee8
commit 44d8200e04
2 changed files with 4 additions and 54 deletions
@@ -613,16 +613,10 @@ describe('pane terminal output scheduler', () => {
expect(terminal.write.mock.calls.map(([data]) => data).join('')).toBe(`${dense}${tail}`)
})
it('paces a latency-sensitive dense foreground redraw instead of writing it whole', async () => {
it('writes a latency-sensitive foreground redraw whole, even when it is dense', async () => {
vi.useFakeTimers()
const { writeTerminalOutput } = await loadScheduler()
const terminal = createForegroundTerminal()
const parsed: (() => void)[] = []
terminal.write.mockImplementation((_data: string, callback?: () => void) => {
if (callback) {
parsed.push(callback)
}
})
const dense = Array.from(
{ length: 1_300 },
(_, index) => `\x1b[${30 + (index % 8)}mX\x1b[0m`
@@ -630,30 +624,9 @@ describe('pane terminal output scheduler', () => {
writeTerminalOutput(terminal, dense, { foreground: true, latencySensitive: true })
// The redraw is queued rather than submitted whole, then released one
// parser batch at a time.
expect(terminal.write).not.toHaveBeenCalled()
vi.advanceTimersByTime(0)
expect(terminal.write).toHaveBeenCalledTimes(1)
expect(terminal.write.mock.calls[0]?.[0]).toHaveLength(4 * 1024)
while (parsed.length > 0) {
parsed.shift()?.()
vi.advanceTimersByTime(0)
}
expect(terminal.write.mock.calls.map(([data]) => data).join('')).toBe(dense)
expect(terminal.write.mock.calls.length).toBeGreaterThan(1)
})
it('writes a latency-sensitive foreground redraw whole when it is not dense', async () => {
vi.useFakeTimers()
const { writeTerminalOutput } = await loadScheduler()
const terminal = createForegroundTerminal()
const plain = 'plain redraw line\r\n'.repeat(1_000)
writeTerminalOutput(terminal, plain, { foreground: true, latencySensitive: true })
expect(terminal.write.mock.calls.map(([data]) => data)).toEqual([plain])
// Pacing this path would delay first paint by a macrotask and multiply the
// per-write viewport settle inside the post-keystroke window.
expect(terminal.write.mock.calls.map(([data]) => data)).toEqual([dense])
})
it('holds the parse probe behind terminal output the flush could not submit', async () => {
@@ -34,7 +34,6 @@ import {
import {
ALWAYS_REFRESH_FOREGROUND_SYNCHRONOUSLY,
BACKGROUND_FLUSH_DELAY_MS,
DENSE_SGR_CHUNK_CHARS,
FOREGROUND_BACKLOG_WARNING,
LARGE_BACKLOG_CHARS,
discardTerminalOutput,
@@ -43,7 +42,6 @@ import {
type TerminalOutputTarget,
type WriteTerminalOutputOptions
} from './pane-terminal-output-queue-registry'
import { isDenseSgr } from '../../../../shared/terminal-sgr-density'
export function writeTerminalOutputImpl(
terminal: TerminalOutputTarget,
@@ -188,27 +186,6 @@ export function writeTerminalOutputImpl(
scheduleDrain(0)
return
}
if (data.length >= DENSE_SGR_CHUNK_CHARS && isDenseSgr(data)) {
const queued = entry ?? createQueueEntry(terminal, options)
queued.onBackgroundBacklogDropped = options.onBackgroundBacklogDropped
queued.highPriority = true
queuedByTerminal.set(terminal, queued)
enqueueChunk(queued, data, {
foreground: true,
forceForegroundRefresh: options.forceForegroundRefresh,
followupForegroundRefresh: options.followupForegroundRefresh,
shouldRefreshForegroundSynchronously: options.shouldRefreshForegroundSynchronously,
stripTransientCursorShows: options.stripTransientCursorShows,
beforeWrite: options.beforeWrite,
onParsed: options.onParsed,
ackCredit: options.ackCredit
})
if (queueCapExceeded(queued)) {
replaceBacklogWithWarning(queued, FOREGROUND_BACKLOG_WARNING)
}
scheduleDrain(0)
return
}
flushTerminalOutputImpl(terminal)
const remaining = queuedByTerminal.get(terminal)
if (remaining) {