Reduce terminal renderer delivery pressure

This commit is contained in:
Neil
2026-06-07 21:09:44 -07:00
parent 51f16757d6
commit 056b5ff4cd
5 changed files with 23 additions and 15 deletions
+11 -11
View File
@@ -4372,7 +4372,7 @@ describe('registerPtyHandlers', () => {
for (let index = 0; index < 400; index++) {
vi.advanceTimersByTime(1)
}
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(512)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(128)
expect(vi.getTimerCount()).toBe(0)
writeListener(null, {
@@ -4381,8 +4381,8 @@ describe('registerPtyHandlers', () => {
})
interactiveProc.emitData('\x1b[20;2Hredraw')
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(513)
expect(mainWindow.webContents.send).toHaveBeenNthCalledWith(513, 'pty:data', {
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(129)
expect(mainWindow.webContents.send).toHaveBeenNthCalledWith(129, 'pty:data', {
id: interactiveSpawn.id,
data: '\x1b[20;2Hredraw'
})
@@ -4396,14 +4396,14 @@ describe('registerPtyHandlers', () => {
})
interactiveProc.emitData(reserveChunk)
}
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(529)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(145)
writeListener(null, {
id: interactiveSpawn.id,
data: 'a'
})
interactiveProc.emitData(reserveChunk)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(529)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(145)
} finally {
vi.useRealTimers()
}
@@ -4439,11 +4439,11 @@ describe('registerPtyHandlers', () => {
vi.advanceTimersByTime(1)
}
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(512)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(128)
ackData(null, { id: spawns[0].id, charCount: 16 * 1024 })
vi.advanceTimersByTime(1)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(513)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(129)
} finally {
vi.useRealTimers()
}
@@ -4479,22 +4479,22 @@ describe('registerPtyHandlers', () => {
for (let index = 0; index < 400; index++) {
vi.advanceTimersByTime(1)
}
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(512)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(128)
const activeIndex = procs.length - 1
procs[activeIndex]!.emitData('active-output')
setActiveRendererPty(null, { id: spawns[activeIndex]!.id, active: true })
vi.advanceTimersByTime(8)
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(513)
expect(mainWindow.webContents.send).toHaveBeenNthCalledWith(513, 'pty:data', {
expect(mainWindow.webContents.send).toHaveBeenCalledTimes(129)
expect(mainWindow.webContents.send).toHaveBeenNthCalledWith(129, 'pty:data', {
id: spawns[activeIndex]!.id,
data: 'active-output'
})
expect(getPtyRendererDeliveryDebugSnapshot()).toMatchObject({
activeRendererPtyCount: 1,
pendingPtyCount: procs.length - 1,
rendererInFlightChars: 8 * 1024 * 1024 + 'active-output'.length
rendererInFlightChars: 2 * 1024 * 1024 + 'active-output'.length
})
ackData(null, { id: spawns[0]!.id, charCount: 16 * 1024 })
} finally {
+1 -1
View File
@@ -1071,7 +1071,7 @@ export function registerPtyHandlers(
const PTY_BATCH_FLUSH_CHUNK_CHARS = 16 * 1024
const PTY_BATCH_FLUSH_MAX_WRITES = 2
const PTY_RENDERER_IN_FLIGHT_HIGH_WATER_CHARS = 512 * 1024
const PTY_RENDERER_TOTAL_IN_FLIGHT_HIGH_WATER_CHARS = 8 * 1024 * 1024
const PTY_RENDERER_TOTAL_IN_FLIGHT_HIGH_WATER_CHARS = 2 * 1024 * 1024
const PTY_RENDERER_INTERACTIVE_RESERVE_CHARS = 256 * 1024
// Why: active panes need a bounded lane through old hidden bulk output so a
// keystroke redraw can reach the renderer before every background ACK lands.
@@ -72,6 +72,8 @@ type HiddenPressureAckGate = {
heldAckChars: number
}
const MAIN_RENDERER_PRESSURE_TARGET_CHARS = 2 * 1024 * 1024
export function pressureOutputScript(runId: string): string {
return `
const paneIndex = process.argv[2] ?? '0'
@@ -196,7 +198,9 @@ export async function runHiddenRealPtyPressureScenario<
expect(debug?.hiddenRendererSkippedChars ?? 0).toBeGreaterThan(0)
expect(pressureBeforeTyping.peakPendingChars).toBeGreaterThan(0)
expect(pressureBeforeTyping.ackGatedFlushSkipCount).toBeGreaterThan(0)
expect(mainPressure?.peakRendererInFlightChars ?? 0).toBeGreaterThanOrEqual(8 * 1024 * 1024)
expect(mainPressure?.peakRendererInFlightChars ?? 0).toBeGreaterThanOrEqual(
MAIN_RENDERER_PRESSURE_TARGET_CHARS
)
expect(ackGate?.heldAckChars ?? 0).toBeGreaterThan(0)
expect(measurement.medianLatencyMs).toBeLessThan(75)
expect(measurement.worstLatencyMs).toBeLessThan(300)
@@ -40,6 +40,7 @@ type MainPressureSchedulerSnapshot = {
}
const MAX_RENDERER_SCHEDULER_QUEUED_CHARS = 2 * 1024 * 1024
const MAIN_RENDERER_PRESSURE_TARGET_CHARS = 2 * 1024 * 1024
type MainPressureDeps<
TMeasurement,
@@ -270,7 +271,9 @@ function expectMainPressureAndTyping<TMeasurement extends MainPressureMeasuremen
}): void {
expect(pressureBeforeTyping.peakPendingChars).toBeGreaterThan(0)
expect(pressureBeforeTyping.ackGatedFlushSkipCount).toBeGreaterThan(0)
expect(mainPressure?.peakRendererInFlightChars ?? 0).toBeGreaterThanOrEqual(8 * 1024 * 1024)
expect(mainPressure?.peakRendererInFlightChars ?? 0).toBeGreaterThanOrEqual(
MAIN_RENDERER_PRESSURE_TARGET_CHARS
)
expect(ackGate?.heldAckChars ?? 0).toBeGreaterThan(0)
expect(scheduler?.droppedBacklogCount ?? Number.POSITIVE_INFINITY).toBe(0)
expect(scheduler?.peakQueuedChars ?? Number.POSITIVE_INFINITY).toBeLessThanOrEqual(
@@ -111,6 +111,7 @@ const HIDDEN_PRESSURE_START_DELAY_MS = 1200
const DEFAULT_FRAME_COUNT = 180
const DEFAULT_FRAME_INTERVAL_MS = 6
const TIMER_SAMPLE_MS = 16
const MAIN_RENDERER_PRESSURE_TARGET_CHARS = 2 * 1024 * 1024
// Why: these are regression budgets, not observed baselines. Repeated local
// 100-pane OpenCode-scale runs are below 50ms worst-key latency; keep enough
// CI headroom while still failing changes that make typing visibly sluggish.
@@ -385,7 +386,7 @@ async function waitForMainPtyPressureBacklog(page: Page): Promise<MainPtyPressur
async () => {
lastSnapshot = await readMainPtyPressureDebug(page)
return (
(lastSnapshot?.peakRendererInFlightChars ?? 0) >= 8 * 1024 * 1024 &&
(lastSnapshot?.peakRendererInFlightChars ?? 0) >= MAIN_RENDERER_PRESSURE_TARGET_CHARS &&
(lastSnapshot?.peakPendingChars ?? 0) > 0 &&
(lastSnapshot?.ackGatedFlushSkipCount ?? 0) > 0
)