Add OpenCode terminal scale benchmarks (#4793)
This commit is contained in:
parent
b88ff2826b
commit
8d78e0cf1e
|
|
@ -0,0 +1,40 @@
|
|||
import { spawn } from 'node:child_process'
|
||||
|
||||
const npxCommand = process.platform === 'win32' ? 'npx.cmd' : 'npx'
|
||||
|
||||
const env = {
|
||||
...process.env,
|
||||
ORCA_E2E_OPENCODE_SCALE_PANES: process.env.ORCA_E2E_OPENCODE_SCALE_PANES ?? '10,25,50,100',
|
||||
ORCA_E2E_OPENCODE_FRAME_COUNT: process.env.ORCA_E2E_OPENCODE_FRAME_COUNT ?? '60'
|
||||
}
|
||||
const extraArgs = process.argv.slice(2)
|
||||
if (extraArgs[0] === '--') {
|
||||
extraArgs.shift()
|
||||
}
|
||||
|
||||
const child = spawn(
|
||||
npxCommand,
|
||||
[
|
||||
'playwright',
|
||||
'test',
|
||||
'tests/e2e/artificial-opencode-terminal-load.spec.ts',
|
||||
'--config',
|
||||
'tests/playwright.config.ts',
|
||||
'--project',
|
||||
'electron-headless',
|
||||
'--workers=1',
|
||||
...extraArgs
|
||||
],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
env
|
||||
}
|
||||
)
|
||||
|
||||
child.on('exit', (code, signal) => {
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal)
|
||||
return
|
||||
}
|
||||
process.exit(code ?? 1)
|
||||
})
|
||||
|
|
@ -61,6 +61,7 @@
|
|||
"build:linux": "pnpm run build:desktop && pnpm run ensure:electron-runtime && electron-builder --config config/electron-builder.config.cjs --linux",
|
||||
"test:e2e": "pnpm run ensure:electron-runtime && npx playwright test --config tests/playwright.config.ts --project electron-headless",
|
||||
"test:e2e:terminal-perf": "pnpm run ensure:electron-runtime && npx playwright test tests/e2e/terminal-typing-latency.spec.ts tests/e2e/terminal-foreground-redraw-freeze.spec.ts tests/e2e/terminal-output-scheduler.spec.ts tests/e2e/terminal-hidden-tui-visual-restore.spec.ts tests/e2e/artificial-opencode-terminal-load.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=2",
|
||||
"test:e2e:terminal-perf:scale": "pnpm run ensure:electron-runtime && node config/scripts/run-terminal-scale-perf-e2e.mjs",
|
||||
"test:e2e:ssh-docker-perf": "node config/scripts/run-ssh-docker-perf-e2e.mjs",
|
||||
"test:e2e:headful": "pnpm run ensure:electron-runtime && npx playwright test --config tests/playwright.config.ts --project electron-headful",
|
||||
"test:e2e:computer": "vitest run --config tests/e2e/vitest.config.ts"
|
||||
|
|
|
|||
|
|
@ -620,6 +620,26 @@ describe('pane terminal output scheduler', () => {
|
|||
setActiveTerminalOutputTarget(terminals[2], false)
|
||||
})
|
||||
|
||||
it('still drains the active terminal first with one hundred queued terminals', async () => {
|
||||
vi.useFakeTimers()
|
||||
const { setActiveTerminalOutputTarget, writeTerminalOutput } = await loadScheduler()
|
||||
const terminals = Array.from({ length: 100 }, () => createTerminal())
|
||||
const activeTerminal = terminals[99]
|
||||
|
||||
terminals.forEach((terminal, index) => {
|
||||
writeTerminalOutput(terminal, `pane-${index}`, { foreground: false })
|
||||
})
|
||||
setActiveTerminalOutputTarget(activeTerminal, true)
|
||||
|
||||
vi.advanceTimersByTime(50)
|
||||
|
||||
expect(activeTerminal.write).toHaveBeenCalledWith('pane-99')
|
||||
expect(terminals[0].write).toHaveBeenCalledWith('pane-0')
|
||||
expect(activeTerminal.write.mock.invocationCallOrder[0]).toBeLessThan(
|
||||
terminals[0].write.mock.invocationCallOrder[0]
|
||||
)
|
||||
})
|
||||
|
||||
it('rotates terminals with remaining backlog behind untouched queued terminals', async () => {
|
||||
vi.useFakeTimers()
|
||||
const { writeTerminalOutput } = await loadScheduler()
|
||||
|
|
|
|||
|
|
@ -84,6 +84,19 @@ function readPositiveInt(name: string, fallback: number): number {
|
|||
return Number.isInteger(value) && value > 0 ? value : fallback
|
||||
}
|
||||
|
||||
function readPositiveIntList(name: string): number[] {
|
||||
const raw = process.env[name]
|
||||
if (!raw) {
|
||||
return []
|
||||
}
|
||||
return raw
|
||||
.split(',')
|
||||
.map((part) => Number(part.trim()))
|
||||
.filter((value, index, values) => {
|
||||
return Number.isInteger(value) && value > 1 && values.indexOf(value) === index
|
||||
})
|
||||
}
|
||||
|
||||
const SAME_WORKSPACE_PANES = readPositiveInt(
|
||||
'ORCA_E2E_OPENCODE_SAME_WORKSPACE_PANES',
|
||||
DEFAULT_SAME_WORKSPACE_PANES
|
||||
|
|
@ -97,6 +110,7 @@ const FRAME_INTERVAL_MS = readPositiveInt(
|
|||
'ORCA_E2E_OPENCODE_FRAME_INTERVAL_MS',
|
||||
DEFAULT_FRAME_INTERVAL_MS
|
||||
)
|
||||
const SCALE_SAME_WORKSPACE_PANES = readPositiveIntList('ORCA_E2E_OPENCODE_SCALE_PANES')
|
||||
|
||||
function interactivePromptScript(runId: string): string {
|
||||
return `
|
||||
|
|
@ -434,6 +448,51 @@ test.describe('Artificial OpenCode terminal load', () => {
|
|||
}
|
||||
})
|
||||
|
||||
for (const paneCount of SCALE_SAME_WORKSPACE_PANES) {
|
||||
test(`keeps typing responsive at ${paneCount} same-workspace OpenCode panes`, async ({
|
||||
orcaPage,
|
||||
testRepoPath
|
||||
}, testInfo) => {
|
||||
await waitForSessionReady(orcaPage)
|
||||
await waitForActiveWorktree(orcaPage)
|
||||
const panes = await ensureActiveWorktreePaneLoad(orcaPage, paneCount)
|
||||
const [typingPane, ...loadPanes] = panes
|
||||
await focusPane(orcaPage, typingPane.paneKey)
|
||||
|
||||
const runId = randomUUID()
|
||||
const scriptPath = path.join(testRepoPath, `.orca-opencode-scale-${paneCount}-${runId}.mjs`)
|
||||
writeFileSync(scriptPath, interactivePromptScript(runId))
|
||||
await resetTerminalPtyOutputDebug(orcaPage)
|
||||
const load = await startSyntheticOpenCodeInjection(
|
||||
orcaPage,
|
||||
loadPanes.map((pane) => pane.paneKey)
|
||||
)
|
||||
try {
|
||||
const measurement = await measureTypingDuringLoad(
|
||||
orcaPage,
|
||||
scriptPath,
|
||||
typingPane.ptyId,
|
||||
runId
|
||||
)
|
||||
annotateTypingMeasurement(
|
||||
testInfo,
|
||||
`opencode-scale-same-workspace-${paneCount}`,
|
||||
panes.length,
|
||||
measurement,
|
||||
await readTerminalPtyOutputDebug(orcaPage),
|
||||
await readTerminalOutputSchedulerDebug(orcaPage)
|
||||
)
|
||||
expect(measurement.medianLatencyMs).toBeLessThan(MAX_MEDIAN_KEY_LATENCY_MS)
|
||||
expect(measurement.worstLatencyMs).toBeLessThan(MAX_WORST_KEY_LATENCY_MS)
|
||||
expect(measurement.maxTimerDriftMs).toBeLessThan(MAX_TIMER_DRIFT_MS)
|
||||
} finally {
|
||||
await load.stop()
|
||||
await sendToTerminal(orcaPage, typingPane.ptyId, '\x03').catch(() => undefined)
|
||||
rmSync(scriptPath, { force: true })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
test('keeps typing responsive while another workspace streams OpenCode-style output', async ({
|
||||
orcaPage,
|
||||
testRepoPath
|
||||
|
|
|
|||
Loading…
Reference in New Issue