@@ -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