Skip to content

Commit 3949192

Browse files
committed
fix(core): compact parser raw outputs over certain size
1 parent 1e82495 commit 3949192

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

packages/nx/src/native/pseudo_terminal/pseudo_terminal.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,17 @@ impl PseudoTerminal {
9191
let quiet_clone = quiet.clone();
9292
let running_clone = running.clone();
9393

94-
let parser = Arc::new(RwLock::new(Parser::new(h, w, 10000)));
94+
// Scrollback size matches PtyInstance::SCROLLBACK_SIZE (1000 rows).
95+
// Larger values make resize reparse and all_contents_formatted() more
96+
// expensive, which blocks the parser write lock and starves rendering.
97+
const SCROLLBACK_SIZE: usize = 1000;
98+
// When raw output exceeds this threshold, compact the parser to prevent
99+
// unbounded Vec growth. Without this, extend_from_slice() eventually
100+
// triggers multi-hundred-millisecond reallocs under the write lock,
101+
// causing the TUI to hang progressively worse as output accumulates.
102+
const MAX_RAW_OUTPUT_BYTES: usize = 5 * 1024 * 1024; // 5 MB
103+
104+
let parser = Arc::new(RwLock::new(Parser::new(h, w, SCROLLBACK_SIZE)));
95105
let parser_clone = parser.clone();
96106
let stdout_tx_clone = stdout_tx.clone();
97107
std::thread::spawn(move || {
@@ -111,7 +121,21 @@ impl PseudoTerminal {
111121
debug!("Read {} bytes", len);
112122
if is_within_nx_tui {
113123
trace!("Processing data via vt100 for use in tui");
114-
parser_clone.write().process(&buf[..len]);
124+
let mut parser = parser_clone.write();
125+
parser.process(&buf[..len]);
126+
// Compact when raw output grows too large. Replays
127+
// the formatted screen state (bounded by SCROLLBACK_SIZE)
128+
// through a fresh parser, keeping raw_output small.
129+
if parser.get_raw_output().len() > MAX_RAW_OUTPUT_BYTES {
130+
let screen = parser.screen();
131+
let (rows, cols) = screen.size();
132+
let formatted = screen.all_contents_formatted();
133+
let scrollback = screen.scrollback();
134+
let mut compacted = Parser::new(rows, cols, SCROLLBACK_SIZE);
135+
compacted.process(&formatted);
136+
compacted.screen_mut().set_scrollback(scrollback);
137+
*parser = compacted;
138+
}
115139
}
116140

117141
if !quiet {

0 commit comments

Comments
 (0)