mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
[1 of 2] Optimize TUI startup terminal probes (#23175)
## Why Codex TUI startup still feels slower than 0.117.0 after the app-server move in 0.118.0. A visible chunk of launch-to-input latency comes from serial terminal startup probes: cursor position, keyboard enhancement support, and default foreground/background color queries can each wait on terminal responses before the first usable frame. Refs #16335. ## What This PR batches the terminal startup probes into one bounded probe. It also reuses the probed cursor position and default colors during TUI setup, fast-paths the primary-device-attributes fallback as keyboard enhancement unsupported, and keeps lightweight startup timing logs for future tuning. The startup telemetry is intentionally left in production: it records phase timings for terminal probes and initial-frame scheduling so future startup regressions can be diagnosed from normal logs rather than re-adding one-off debug instrumentation. ## Benchmark In the local pty startup benchmark, the pre-optimization `main` baseline was about 250.5ms median from launch to accepted chat input. This probe-only branch measured about 152ms median, for an approximate savings of 95-100ms. ## Stack 1. [#23175: [1 of 2] Optimize TUI startup terminal probes](https://github.com/openai/codex/pull/23175) — this PR 2. [#23176: [2 of 2] Start fresh TUI thread in background](https://github.com/openai/codex/pull/23176) — layered on this PR ## Verification - `cargo test -p codex-tui`
This commit is contained in:
1 parent
e734cb5713
commit
adca1b643f
5 files changed
+254
-73
No files matched your search
+61
-23
@@ -63,6 +63,11 @@ pub(crate) const TARGET_FRAME_INTERVAL: Duration = frame_rate_limiter::MIN_FRAME
|
||||
/// A type alias for the terminal type used in this application
|
||||
pub type Terminal = CustomTerminal<CrosstermBackend<Stdout>>;
|
||||
|
||||
pub(crate) struct InitializedTerminal {
|
||||
pub(crate) terminal: Terminal,
|
||||
pub(crate) enhanced_keys_supported: bool,
|
||||
}
|
||||
|
||||
pub(crate) fn running_in_vscode_terminal() -> bool {
|
||||
keyboard_modes::running_in_vscode_terminal()
|
||||
}
|
||||
@@ -334,7 +339,7 @@ fn flush_terminal_input_buffer() {
|
||||
pub(crate) fn flush_terminal_input_buffer() {}
|
||||
|
||||
/// Initialize the terminal (inline viewport; history stays in normal scrollback)
|
||||
pub fn init() -> Result<Terminal> {
|
||||
pub(crate) fn init() -> Result<InitializedTerminal> {
|
||||
if !stdin().is_terminal() {
|
||||
return Err(std::io::Error::other("stdin is not a terminal"));
|
||||
}
|
||||
@@ -351,20 +356,57 @@ pub fn init() -> Result<Terminal> {
|
||||
let backend = CrosstermBackend::new(stdout());
|
||||
|
||||
#[cfg(unix)]
|
||||
let cursor_pos =
|
||||
match crate::terminal_probe::cursor_position(crate::terminal_probe::DEFAULT_TIMEOUT) {
|
||||
Ok(Some(pos)) => pos,
|
||||
Ok(None) => {
|
||||
tracing::warn!("initial cursor position probe timed out; defaulting to origin");
|
||||
Position { x: 0, y: 0 }
|
||||
let startup_probe = {
|
||||
use crate::terminal_probe::StartupKeyboardEnhancementProbe;
|
||||
|
||||
let started_at = std::time::Instant::now();
|
||||
let keyboard_probe = if keyboard_modes::keyboard_enhancement_disabled() {
|
||||
StartupKeyboardEnhancementProbe::Skip
|
||||
} else {
|
||||
StartupKeyboardEnhancementProbe::Query
|
||||
};
|
||||
match crate::terminal_probe::startup(crate::terminal_probe::DEFAULT_TIMEOUT, keyboard_probe)
|
||||
{
|
||||
Ok(probe) => {
|
||||
tracing::info!(
|
||||
duration_ms = %started_at.elapsed().as_millis(),
|
||||
cursor_position = probe.cursor_position.is_some(),
|
||||
default_colors = probe.default_colors.is_some(),
|
||||
keyboard_enhancement_supported = ?probe.keyboard_enhancement_supported,
|
||||
"terminal startup probes completed"
|
||||
);
|
||||
probe
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::warn!(
|
||||
"failed to read initial cursor position; defaulting to origin: {err}"
|
||||
duration_ms = %started_at.elapsed().as_millis(),
|
||||
"terminal startup probes failed: {err}"
|
||||
);
|
||||
Position { x: 0, y: 0 }
|
||||
crate::terminal_probe::StartupProbe {
|
||||
cursor_position: None,
|
||||
default_colors: None,
|
||||
keyboard_enhancement_supported: None,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
crate::terminal_palette::set_default_colors_from_startup_probe(startup_probe.default_colors);
|
||||
|
||||
#[cfg(unix)]
|
||||
let cursor_pos = match startup_probe.cursor_position {
|
||||
Some(pos) => pos,
|
||||
None => {
|
||||
tracing::warn!("initial cursor position probe timed out; defaulting to origin");
|
||||
Position { x: 0, y: 0 }
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
let enhanced_keys_supported = startup_probe
|
||||
.keyboard_enhancement_supported
|
||||
.unwrap_or(/*default*/ false);
|
||||
|
||||
#[cfg(not(unix))]
|
||||
let mut backend = CrosstermBackend::new(stdout());
|
||||
@@ -372,8 +414,15 @@ pub fn init() -> Result<Terminal> {
|
||||
#[cfg(not(unix))]
|
||||
let cursor_pos = cursor_position_with_crossterm(&mut backend);
|
||||
|
||||
#[cfg(not(unix))]
|
||||
let enhanced_keys_supported =
|
||||
!keyboard_modes::keyboard_enhancement_disabled() && detect_keyboard_enhancement_supported();
|
||||
|
||||
let tui = CustomTerminal::with_options_and_cursor_position(backend, cursor_pos)?;
|
||||
Ok(tui)
|
||||
Ok(InitializedTerminal {
|
||||
terminal: tui,
|
||||
enhanced_keys_supported,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
@@ -384,13 +433,6 @@ fn cursor_position_with_crossterm(backend: &mut CrosstermBackend<Stdout>) -> Pos
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn detect_keyboard_enhancement_supported() -> bool {
|
||||
crate::terminal_probe::keyboard_enhancement_supported(crate::terminal_probe::DEFAULT_TIMEOUT)
|
||||
.unwrap_or(/*default*/ None)
|
||||
.unwrap_or(/*default*/ false)
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn detect_keyboard_enhancement_supported() -> bool {
|
||||
// Non-Unix startup keeps the existing crossterm path because the bounded probe implementation
|
||||
@@ -461,14 +503,10 @@ where
|
||||
}
|
||||
|
||||
impl Tui {
|
||||
pub fn new(terminal: Terminal) -> Self {
|
||||
pub fn new(terminal: Terminal, enhanced_keys_supported: bool) -> Self {
|
||||
let (draw_tx, _) = broadcast::channel(1);
|
||||
let frame_requester = FrameRequester::new(draw_tx.clone());
|
||||
|
||||
// Detect keyboard enhancement support before any EventStream is created so the
|
||||
// crossterm poller can acquire its lock without contention.
|
||||
let enhanced_keys_supported = !keyboard_modes::keyboard_enhancement_disabled()
|
||||
&& detect_keyboard_enhancement_supported();
|
||||
// Cache this to avoid contention with the event reader.
|
||||
supports_color::on_cached(supports_color::Stream::Stdout);
|
||||
let _ = crate::terminal_palette::default_colors();
|
||||
|
||||
Reference in new issue
Block a user