mirror of
https://github.com/stablyai/orca.git
synced 2026-10-29 08:07:18 +00:00
Hidden panes are exempt from pendingData flow control (main gate-drops their bytes after ingestion), so N background agents ran unbounded ahead on the one shared daemon->main stream socket (measured 192MB user-space backlog) and visible-pane echo waited FIFO behind it — typing appeared seconds late whenever several agents burst on a loaded machine (8x512KB/s + 12 CPU spinners: p50 293ms fix-off; 12x1MB/s: 6.1s). Mechanism (replaces producer pacing — no reveal catch-up, ever): - Shallow socket write gate (128KB) + per-session fairness bypass bounds echo latency by construction; kernel-flush refill sentinel keeps held bulk draining at full speed (drain-only refill capped at ~8MB/s). - Backgrounded sessions' queued output is keep-tail dropped (newest 512KB kept, in-order dataGap replaces the middle); a ~2MB GLOBAL budget shrinks per-session keep-tails (floor 64KB) so a worktree switch never waits behind the aggregate. Reply-eliciting query bytes (DSR/DA/OSC probes) are salvaged from dropped spans. - Notifications are structurally lossless: the daemon runs the same shared scanners main uses (bell/OSC 133/pr-link/2031) over every byte BEFORE drop decisions and relays facts in byte order; ordered background markers hand scan authority back and forth, seeded with the emulator's partial escape tail so a sequence split across the handoff neither phantom-fires nor goes missing. Titles/agent-status stay main-side (kept-tail convergent). - Main: background = hidden AND no remote view subscriber (a live mobile/web view is never thinned); on dataGap main resets cross-chunk parse carries, drops the headless mobile mirror, and reuses the hidden-drop model-restore marker. Wire: three new stream events, tolerated within protocol v19 (old mains ignore unknown events; old daemons never see the trigger). Kill switches: ORCA_DAEMON_BACKGROUND_STREAM_DROP=0, ORCA_DAEMON_SHALLOW_SOCKET_GATE=0. A/B (pnpm bench:multi-workspace-typing): 8x512KB/s + 12 CPU workers p50 293ms/p90 647ms -> 15/21ms (= baseline); 12x1MB/s 6,146ms -> 20ms; light loads unchanged; zero missing echoes. Latin hidden-restore e2e green (probe-verified aggregate-drain root cause). New deterministic repro harness: tests/e2e/terminal-multi-workspace-typing-latency.spec.ts + CPU pressure workers. Co-authored-by: Orca <help@stably.ai>
64 lines
1.6 KiB
JavaScript
64 lines
1.6 KiB
JavaScript
/**
|
|
* Entry point for the multi-workspace typing-latency bench
|
|
* (tests/e2e/terminal-multi-workspace-typing-latency.spec.ts).
|
|
*
|
|
* Usage:
|
|
* pnpm bench:multi-workspace-typing [-- --panes 8 --rate-kbps 512 \
|
|
* --keys 48 --cadence-ms 250 --cpu-workers 4 --label before-fix]
|
|
*
|
|
* Results land in tools/benchmarks/results/multi-workspace-typing-*.json.
|
|
* Run once per build/config with distinct --label values, then diff the
|
|
* totalMs/inputHalfMs/echoHalfMs percentiles.
|
|
*/
|
|
import { spawn } from 'node:child_process'
|
|
|
|
const npxCommand = process.platform === 'win32' ? 'npx.cmd' : 'npx'
|
|
|
|
const knobByFlag = {
|
|
'--panes': 'ORCA_TYPING_BENCH_LOAD_PANES',
|
|
'--rate-kbps': 'ORCA_TYPING_BENCH_RATE_KBPS',
|
|
'--keys': 'ORCA_TYPING_BENCH_KEYS',
|
|
'--cadence-ms': 'ORCA_TYPING_BENCH_KEY_CADENCE_MS',
|
|
'--cpu-workers': 'ORCA_TYPING_BENCH_CPU_WORKERS',
|
|
'--label': 'ORCA_TYPING_BENCH_LABEL'
|
|
}
|
|
|
|
const env = { ...process.env, ORCA_TYPING_BENCH: '1' }
|
|
const passthroughArgs = []
|
|
const argv = process.argv.slice(2)
|
|
for (let i = 0; i < argv.length; i++) {
|
|
if (argv[i] === '--') {
|
|
continue
|
|
}
|
|
const knob = knobByFlag[argv[i]]
|
|
if (knob) {
|
|
env[knob] = argv[++i]
|
|
} else {
|
|
passthroughArgs.push(argv[i])
|
|
}
|
|
}
|
|
|
|
const child = spawn(
|
|
npxCommand,
|
|
[
|
|
'playwright',
|
|
'test',
|
|
'tests/e2e/terminal-multi-workspace-typing-latency.spec.ts',
|
|
'--config',
|
|
'tests/playwright.config.ts',
|
|
'--project',
|
|
'electron-headless',
|
|
'--workers=1',
|
|
...passthroughArgs
|
|
],
|
|
{ stdio: 'inherit', env }
|
|
)
|
|
|
|
child.on('exit', (code, signal) => {
|
|
if (signal) {
|
|
process.kill(process.pid, signal)
|
|
return
|
|
}
|
|
process.exit(code ?? 1)
|
|
})
|