Skip to content

CRITICAL: Fix runaway CPU usage and React render loop on project workspace pages#100

Open
SmallSpider0 wants to merge 1 commit into
ResearAI:mainfrom
SmallSpider0:fix/project-workspace-runaway-cpu
Open

CRITICAL: Fix runaway CPU usage and React render loop on project workspace pages#100
SmallSpider0 wants to merge 1 commit into
ResearAI:mainfrom
SmallSpider0:fix/project-workspace-runaway-cpu

Conversation

@SmallSpider0
Copy link
Copy Markdown

Summary

This PR fixes a severe production-impacting performance bug where opening an idle project workspace page, such as /projects/004, could continuously consume more than one full CPU core.

The issue was severe because a normal idle web page could keep browser CPU usage around 120%+ on user hardware and over 200% in automated profiling, causing laptop overheating and making the workspace unsafe to leave open.

Severity

Critical / High severity

Before this fix, simply opening an idle project page could cause sustained high CPU usage:

  • User report: ~120% CPU on an M4 Mac
  • Reproduction in Playwright/Chromium: over 200% total browser CPU
  • Continuous React update loop warnings were observed during root-cause isolation
  • The page remained hot even when the user was not interacting with it

This is not expected behavior for an idle research workspace page.

Root Cause

The CPU issue had multiple contributing causes:

  1. Runaway React render/update loop in the Copilot dock

    • CopilotDockCallbacksContext.Provider recreated a new context value object on every render.
    • QuestCopilotDockPanel had effects depending on that context object.
    • Those effects called onHeaderExtraChange, onMetaChange, and related setters repeatedly.
    • This produced continuous React commits and Maximum update depth exceeded warnings.
  2. Idle copilot workspaces were incorrectly treated as live/running

    • Quest 004 had active_run_id: null and was in wait_for_user_or_resume.
    • However, historical/terminal bash sessions still contributed to bash_running_count.
    • The UI therefore treated a parked copilot workspace as active work.
    • This kept busy state, polling/streaming paths, and active UI updates alive.
  3. Bash operation cards performed unstable state propagation

    • QuestBashExecOperation parsed structured args/output on every render, creating fresh objects.
    • Live bash progress/status callbacks were recreated and could report equivalent state repeatedly.
    • McpBashExecView also reported unchanged live state back to the parent.
    • This amplified re-rendering across dozens of bash operation cards.
  4. Bash session stream updates were not sufficiently deduplicated

    • Repeated equivalent session events caused unnecessary React state updates.
    • Session updates are now deduplicated and batched.
  5. Idle decorative workspace animations added avoidable GPU/renderer work

    • Decorative background blob/noise animations were disabled on the heavy project workspace surfaces so an idle workspace can remain effectively idle.

Fix

This PR:

  • Memoizes the Copilot dock callback context value.
  • Guards Copilot metadata/header updates against identical state.
  • Detects stale parked copilot workspaces correctly when:
    • workspace_mode === "copilot"
    • continuation_policy === "wait_for_user_or_resume"
    • active_run_id is absent
    • latest tool activity is stale
  • Stabilizes QuestBashExecOperation by:
    • memoizing parsed args/output/progress
    • using stable live-state callbacks
    • avoiding state updates when progress/status values are unchanged
  • Stabilizes McpBashExecView by:
    • suppressing duplicate onLiveStateChange emissions
    • guarding equivalent progress/status setters
  • Deduplicates and batches bash session stream updates.
  • Memoizes expensive Studio trace blocks to avoid unnecessary remount/re-render work.
  • Disables idle decorative workspace background animations on project workspace surfaces.

CPU Usage Report

Before Fix

Initial production/dev reproduction showed sustained runaway CPU:

Measurement Total Browser CPU Renderer CPU GPU CPU
Live reproduction ~225.3% ~138.6% ~86.5%
Dev reproduction ~242.2% ~152.4% ~89.5%

Additional root-cause probe:

  • React update loop warnings: Maximum update depth exceeded
  • Console warning count during reproduction: 168 warnings in a 10s sampling window
  • React commit probe showed continuous commits while idle

After Fix

Final deployed live measurement:

Measurement Total Browser CPU Renderer CPU GPU CPU
Live after fix ~7.3% ~6.9% ~0.1%

Final verification:

  • Active animation list: []
  • Console warnings/errors from update loop: 0
  • Live bundle verified: /ui/assets/index-qDSXrMaL.js

Testing

Passed:

git diff --check
npm --prefix src/ui run build

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant