Skip to content

fix(core): throttle shell text output to prevent UI jank on high-volu… - #27010

Closed
TirthNaik-99 wants to merge 1 commit into
google-gemini:mainfrom
TirthNaik-99:fix/shell-text-output-throttle
Closed

fix(core): throttle shell text output to prevent UI jank on high-volu…#27010
TirthNaik-99 wants to merge 1 commit into
google-gemini:mainfrom
TirthNaik-99:fix/shell-text-output-throttle

Conversation

@TirthNaik-99

Copy link
Copy Markdown
Contributor

Shell tool data events triggered a React re-render on every chunk while binary_progress was already throttled to 1s intervals. Commands emitting thousands of lines pinned the UI until exit.

Apply OUTPUT_UPDATE_INTERVAL_MS (1s) throttling to text data events, matching the existing binary_progress throttle. This prevents thousands of React re-renders when commands emit high-volume output (builds, verbose test runs, npm install warnings).

Key changes:

  • First text chunk renders immediately (lastUpdateTime starts at 0)
  • PTY (AnsiOutput) snapshots bypass throttle (already debounced at 68ms)
  • Trailing-edge flush ensures buffered output appears when command goes silent
  • Exit event flushes remaining output and cancels pending timers

Fixes #25459

Summary

Apply OUTPUT_UPDATE_INTERVAL_MS (1s) throttling to shell text data events in both the core tool (shell.ts) and the CLI UI hook (useExecutionLifecycle.ts), matching the existing binary_progress cadence. High-volume commands (builds, verbose test runs) no longer pin the terminal UI with thousands of React re-renders.

Details

  • lastUpdateTime starts at 0 so the very first text chunk renders immediately (no initial 1s blank)
  • PTY AnsiOutput snapshots bypass the throttle entirely — they are already debounced at 68ms in shellExecutionService
  • A trailing-edge setTimeout flush ensures buffered output appears even when a command emits a burst then goes silent
  • The exit event flushes remaining output and cancels any pending trailing timer
  • Final complete output is unaffected — it is rendered from the full result returned by shellExecutionService after the command exits

Related Issues

Fixes #25459

How to Validate

  1. Run unit tests: npx vitest run packages/core/src/tools/shell.test.ts — all 82 tests pass (4 new regression tests)
  2. Run a high-volume shell command from inside the CLI: for i in $(seq 1 20000); do echo "line $i"; done
  3. Verify the UI stays responsive while the command runs (no freeze, input stays interactive) and the final output is complete and correct
  4. Run a PTY-style command (e.g. anything with ANSI progress bars) and verify updates still appear at full rate (no throttle on PTY)

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

…me commands

Apply OUTPUT_UPDATE_INTERVAL_MS (1s) throttling to text data events,
matching the existing binary_progress throttle. This prevents thousands
of React re-renders when commands emit high-volume output (builds,
verbose test runs, npm install warnings).

Key changes:
- First text chunk renders immediately (lastUpdateTime starts at 0)
- PTY (AnsiOutput) snapshots bypass throttle (already debounced at 68ms)
- Trailing-edge flush ensures buffered output appears when command goes silent
- Exit event flushes remaining output and cancels pending timers

Fixes google-gemini#25459
@TirthNaik-99
TirthNaik-99 requested review from a team as code owners May 13, 2026 18:46
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses performance degradation in the terminal UI when executing commands that produce high-volume text output. By applying a 1-second throttle to shell data events, the system avoids flooding the React render cycle, significantly improving UI responsiveness during long-running processes like builds or verbose test suites. The implementation includes robust handling for trailing flushes and process exits to ensure no output is lost, while specifically exempting PTY-based output to maintain expected terminal behavior.

Highlights

  • Performance Optimization: Implemented a 1s throttle on shell text data events to prevent UI jank caused by excessive React re-renders during high-volume command output.
  • Throttling Logic: Added a trailing-edge flush mechanism to ensure that buffered output is rendered even when a command stops emitting data, and ensured the first chunk renders immediately.
  • PTY Preservation: Ensured that PTY (AnsiOutput) snapshots bypass the new throttle, maintaining the existing 68ms debounce cadence for terminal-based output.
  • Lifecycle Management: Updated the 'exit' event handling to flush any remaining buffered output and cancel pending timers, ensuring data integrity upon command completion.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions

Copy link
Copy Markdown

🛑 Action Required: Evaluation Approval

Steering changes have been detected in this PR. To prevent regressions, a maintainer must approve the evaluation run before this PR can be merged.

Maintainers:

  1. Go to the Workflow Run Summary.
  2. Click the yellow 'Review deployments' button.
  3. Select the 'eval-gate' environment and click 'Approve'.

Once approved, the evaluation results will be posted here automatically.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces output throttling for shell command execution in both the CLI UI and the core shell tool to improve performance during high-volume output. It implements a timer-based mechanism to ensure a final flush of data and adds comprehensive unit tests for these scenarios. The review feedback suggests ensuring that these timers are properly cleared in finally blocks to prevent potential memory leaks or unexpected state updates if an execution is aborted or encounters an error.

Comment on lines +488 to +491
if (trailingFlushTimer !== null) {
clearTimeout(trailingFlushTimer);
trailingFlushTimer = null;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The trailingFlushTimer should also be cleared in the finally block of the executeCommand function (around line 659). This ensures that no pending timers are left dangling if the command execution is aborted or encounters an error before completion, preventing potential state updates on an unmounted component or after the execution context has been cleaned up.

Comment on lines +594 to +597
if (trailingFlushTimer !== null) {
clearTimeout(trailingFlushTimer);
trailingFlushTimer = null;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The trailingFlushTimer should be cleared in the finally block of the execute method (around line 998). While it is cleared here during active updates, an early return or error in the execution flow could leave a timer pending, potentially calling updateOutput after the invocation has finished.

@gemini-cli gemini-cli Bot added priority/p2 Important but can be addressed in a future release. area/core Issues related to User Interface, OS Support, Core Functionality help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! labels May 13, 2026
@scidomino

Copy link
Copy Markdown
Collaborator

we already have #26955 that is in the process of getting merged.

@scidomino scidomino closed this May 13, 2026
@sripasg sripasg added the size/m A medium sized PR label Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Issues related to User Interface, OS Support, Core Functionality help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! priority/p2 Important but can be addressed in a future release. size/m A medium sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shell tool text output causes UI jank on high-volume commands

3 participants