Files
orca/src/shared/darwin-process-table-capture.ts
T
db2ed7ca36 perf(mac): name terminals in Orca instead of ps tty= (#27146)
Ask ps for raw terminal device numbers and name them in Orca: a verified direct lookup of /dev/ttys<minor> per distinct terminal, with an exact first-alias /dev scan fallback. Removes Apple ps's per-row /dev scan (~1 s CPU per capture on a busy Mac).

Fixes #24889

Co-authored-by: Giorgio Zamparelli <giorgio.zamparelli@gmail.com>
Co-authored-by: out-of-place <contact@outofplace.space>
2026-10-10 16:45:23 -07:00

95 lines
2.8 KiB
TypeScript

import { nameDarwinTerminals } from './darwin-terminal-names'
import { errorMessage } from './error-message'
import { ProcessTableCaptureError, PS_ARGS } from './process-table-snapshot'
import { withTimeout } from './promise-timeout-fallback'
let deviceColumnUnsupported = false
let terminalNamingInFlight: Promise<string> | null = null
export async function captureDarwinProcessTable(
capture: (args: readonly string[], timeoutMs?: number) => Promise<string>,
validate: (stdout: string) => string,
budgetMs: number
): Promise<string> {
const startedAt = performance.now()
const remainingBudget = (): number => {
const remaining = Math.floor(budgetMs - (performance.now() - startedAt))
if (remaining <= 0) {
throw new ProcessTableCaptureError('capture_over_budget')
}
return remaining
}
const canonicalCapture = (): Promise<string> => capture(PS_ARGS, remainingBudget())
if (deviceColumnUnsupported || terminalNamingInFlight) {
return canonicalCapture()
}
let captured: string
try {
captured = await capture(['-axo', PS_ARGS[1].replace('tty=', 'tdev=')], remainingBudget())
} catch (error) {
if (
!(error instanceof Error) ||
!('code' in error) ||
(error.code !== 1 && error.code !== 2) ||
('killed' in error && error.killed === true) ||
!/^(?:ps: tdev: keyword not found|error: unknown user-defined format specifier "tdev")$/m.test(
errorMessage(error)
)
) {
throw error
}
deviceColumnUnsupported = true
return canonicalCapture()
}
remainingBudget()
if (terminalNamingInFlight) {
return canonicalCapture()
}
const controller = new AbortController()
const pending = nameDarwinTerminals(captured, undefined, controller.signal)
terminalNamingInFlight = pending
// Uncancelable filesystem calls keep the slot until they drain.
const clearNaming = (): void => {
if (terminalNamingInFlight === pending) {
terminalNamingInFlight = null
}
}
void pending.then(clearNaming, clearNaming)
let remainingMs: number
try {
remainingMs = remainingBudget()
} catch (error) {
controller.abort()
throw error
}
const named = await withTimeout<{ value: string } | { error: unknown } | null>(
pending.then(
(value) => ({ value }),
(error: unknown) => ({ error })
),
remainingMs,
null
)
if (named === null) {
controller.abort()
throw new ProcessTableCaptureError('capture_over_budget')
}
remainingBudget()
if ('error' in named) {
return canonicalCapture()
}
let validated: string
try {
validated = validate(named.value)
} catch {
return canonicalCapture()
}
remainingBudget()
return validated
}
export function resetDarwinProcessTableCaptureForTests(): void {
deviceColumnUnsupported = false
terminalNamingInFlight = null
}