Skip to content

perf(server): cut chatty tool-update frames by 90% - #8368

Open
Adamulek123 wants to merge 1 commit into
pingdotgg:mainfrom
Adamulek123:perf/coalesce-tool-updates
Open

perf(server): cut chatty tool-update frames by 90%#8368
Adamulek123 wants to merge 1 commit into
pingdotgg:mainfrom
Adamulek123:perf/coalesce-tool-updates

Conversation

@Adamulek123

@Adamulek123 Adamulek123 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

What changed

The thread WebSocket stream now coalesces live tool.updated events in a bounded 50 ms window. It keeps the newest update per tool call, lets completion supersede preceding updates, and preserves sequence and synchronization-marker ordering.

Why

Chatty tools can emit many updates for one call. The server previously sent every update as a separate frame even though clients ultimately render the newest state and completion. This creates avoidable remote traffic and frame processing.

Measured impact

Compared with main-latest.json from main commit 230c5d4a, using twenty deterministic updates followed by completion:

Live tool-update burst Main This PR Change
WebSocket wire 7,155 B 599 B -6,556 B (-91.6%)
WebSocket decoded 7,071 B 591 B -6,480 B (-91.6%)
Messages 21 2 -19 (-90.5%)

The broader measured-turn scenario reduced live messages from 11 to 8 for both Codex and Claude. Snapshot traffic remains within 0.1% of main. Every enforced ceiling passes.

Validation

  • vp test run apps/server/test/ActivityPayloadProjection.test.ts, 21 tests passed
  • Three focused WebSocket integration tests in apps/server/src/server.test.ts
  • vp exec tsgo -p apps/server/tsconfig.json --noEmit
  • Focused lint and formatting
  • Deterministic transfer and tool-burst benchmark guards

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes

Generated with GPT-5.6 Sol through the Codex harness.


Note

Medium Risk
Changes real-time orchestration WebSocket delivery semantics (fewer frames, same identity rules as snapshot slimming), so ordering edge cases around sync markers and parallel tool calls need careful review.

Overview
Live thread subscriptions now batch thread.activity-appended events through a 50 ms / 512-event window and run coalesceLiveToolUpdatedEvents before projecting payloads, so chatty tool.updated traffic collapses to the latest update per tool call (per turn + lifecycle identity). tool.completed still wins over earlier updates for the same call, and non-tool events, anonymous activities, and cross-turn identities are left alone.

The WebSocket path mirrors the existing shell coalescing pattern: events are buffered as raw **OrchestrationEvent**s, synchronized markers flush the pending window without being reordered ahead of in-flight updates, and survivors keep sequence order for client dedup. Snapshots still use dropSupersededToolUpdatedActivities on persisted activities; this change targets live streaming only.

Unit tests cover coalescing rules; an integration test asserts subscribeThread delivers sequence 4 after three buffered updates for one toolCallId.

Reviewed by Cursor Bugbot for commit 8995244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Coalesce live tool.updated events in subscribeThread to cut WS frames by 90%

  • Adds coalesceLiveToolUpdatedEvents to keep only the latest tool.updated per tool call (per turn) and let any tool.completed supersede earlier updates in the same batch
  • coalesceThreadLiveStream groups incoming live events by a 50ms / 512-event window, applies coalescing per segment, and projects events after coalescing so sequence numbers stay correct
  • subscribeThread now queues raw OrchestrationEvent objects and flushes at synchronized markers (including requestCompletionMarker, snapshot, and catch-up replay) so coalescing never crosses a flush boundary
  • Risk: event projection in ws.ts now happens post-coalescing; if a client relied on receiving every intermediate tool.updated frame, those are dropped within each 50ms window. The THREAD_TOOL_UPDATE_COALESCE_WINDOW and THREAD_TOOL_UPDATE_COALESCE_MAX_CHUNK constants control the trade-off

Macroscope summarized 8995244.

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f2a5a1d5-77f3-412e-886f-71acbb19068d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 27, 2026
@Adamulek123
Adamulek123 force-pushed the perf/coalesce-tool-updates branch from d532cc5 to 8995244 Compare August 27, 2026 07:32
@Adamulek123
Adamulek123 marked this pull request as ready for review August 27, 2026 07:51
@macroscopeapp

macroscopeapp Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The production thread WebSocket path now batches live events and intentionally suppresses intermediate tool-update frames, changing delivery timing and observable stream behavior for existing subscribers. The marker-aware buffering and sequence-preservation logic make this more than a small isolated optimization.

You can add or adjust custom eligibility rules. Learn more.

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

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant