perf(tui2): reduce unnecessary redraws (#8681)
This reduces unnecessary frame scheduling in codex-tui2. Changes: - Gate redraw scheduling for streaming deltas when nothing visible changes. - Avoid a redraw feedback loop from footer transcript UI state updates. Why: - Streaming deltas can arrive at very high frequency; redrawing on every delta can drive a near-constant render loop. - BottomPane was requesting another frame after every Draw even when the derived transcript UI state was unchanged. Testing: - cargo test -p codex-tui2 Manual sampling: - sample "$(pgrep -n codex-tui2)" 3 -file /tmp/tui2.idle.after.sample.txt - sample "$(pgrep -n codex-tui2)" 3 -file /tmp/tui2.streaming.after.sample.txt
This commit is contained in:
parent
ab753387cc
commit
3cfa4bc8be
3 changed files with 20 additions and 4 deletions
|
|
@ -1577,11 +1577,20 @@ impl ChatComposer {
|
|||
selection_active: bool,
|
||||
scroll_position: Option<(usize, usize)>,
|
||||
copy_selection_key: KeyBinding,
|
||||
) {
|
||||
) -> bool {
|
||||
if self.transcript_scrolled == scrolled
|
||||
&& self.transcript_selection_active == selection_active
|
||||
&& self.transcript_scroll_position == scroll_position
|
||||
&& self.transcript_copy_selection_key == copy_selection_key
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
self.transcript_scrolled = scrolled;
|
||||
self.transcript_selection_active = selection_active;
|
||||
self.transcript_scroll_position = scroll_position;
|
||||
self.transcript_copy_selection_key = copy_selection_key;
|
||||
true
|
||||
}
|
||||
|
||||
fn sync_popups(&mut self) {
|
||||
|
|
|
|||
|
|
@ -389,13 +389,15 @@ impl BottomPane {
|
|||
scroll_position: Option<(usize, usize)>,
|
||||
copy_selection_key: crate::key_hint::KeyBinding,
|
||||
) {
|
||||
self.composer.set_transcript_ui_state(
|
||||
let updated = self.composer.set_transcript_ui_state(
|
||||
scrolled,
|
||||
selection_active,
|
||||
scroll_position,
|
||||
copy_selection_key,
|
||||
);
|
||||
self.request_redraw();
|
||||
if updated {
|
||||
self.request_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
/// Show a generic list selection view with the provided items.
|
||||
|
|
|
|||
|
|
@ -968,6 +968,7 @@ impl ChatWidget {
|
|||
if let Some(cell) = cell {
|
||||
self.bottom_pane.hide_status_indicator();
|
||||
self.add_boxed_history(cell);
|
||||
self.request_redraw();
|
||||
}
|
||||
if is_idle {
|
||||
self.app_event_tx.send(AppEvent::StopCommitAnimation);
|
||||
|
|
@ -1009,6 +1010,7 @@ impl ChatWidget {
|
|||
#[inline]
|
||||
fn handle_streaming_delta(&mut self, delta: String) {
|
||||
// Before streaming agent content, flush any active exec cell group.
|
||||
let mut needs_redraw = self.active_cell.is_some();
|
||||
self.flush_active_cell();
|
||||
|
||||
if self.stream_controller.is_none() {
|
||||
|
|
@ -1019,6 +1021,7 @@ impl ChatWidget {
|
|||
.map(super::status_indicator_widget::StatusIndicatorWidget::elapsed_seconds);
|
||||
self.add_to_history(history_cell::FinalMessageSeparator::new(elapsed_seconds));
|
||||
self.needs_final_message_separator = false;
|
||||
needs_redraw = true;
|
||||
}
|
||||
self.stream_controller = Some(StreamController::new(
|
||||
self.last_rendered_width.get().map(|w| w.saturating_sub(2)),
|
||||
|
|
@ -1029,7 +1032,9 @@ impl ChatWidget {
|
|||
{
|
||||
self.app_event_tx.send(AppEvent::StartCommitAnimation);
|
||||
}
|
||||
self.request_redraw();
|
||||
if needs_redraw {
|
||||
self.request_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handle_exec_end_now(&mut self, ev: ExecCommandEndEvent) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue