Skip to content

perf(fleet): linear-time SSE frame splitting in the relay and app readers #1779

Closed

Description

@jeonghun-jj-lee

Important

Problem — Both SSE readers on the path re-scan their entire partial buffer on every network chunk. The relay's upstream reader appends each chunk and searches for the frame delimiter from the start; the app's stream reader re-normalizes line endings and re-splits the whole buffer on every chunk, on the webview's main thread. A multi-MB frame arriving in tens of chunks therefore costs quadratic time and stalls everything queued behind it.
Approach — Make both readers incremental: search for the delimiter only in newly received data (carrying over a one-character boundary), normalize line endings only on new data, and accumulate partial frames without repeated copying.
Scope — in: the relay's upstream frame splitter; the app's stream reader. out: JSON parse cost; store reconciliation cost.
Assumptions — The app's reader can be replaced through the overlay (it is generated SDK code) or wrapped in the app without changing the SDK's public surface.

Acceptance Criteria

  • A 10 MB frame delivered in 64 KB chunks is split by each reader in time within a small constant factor of the same frame delivered in one chunk.
  • Frame boundaries split across chunks are handled correctly, including a delimiter split between two chunks and CRLF line endings split between chunks.
  • Existing framing behavior is unchanged: multi-line data, event names, ids, and retry fields.

Testing Decisions

  • Extend the driver pump suite and add a reader test in the app, both using the census slice's chunked large-frame fixture; assert a time ratio, not absolute times.

Key Decisions

  • Carry over one character across chunks for the two-character delimiter; normalize CRLF per chunk, carrying a trailing carriage return over to the next chunk.

Constraints & Invariants

Prior Art

  • The relay's frame-preserving upstream reader; the generated SDK stream reader the app uses.

Source

Notes

  • Related, not in scope: the extension host's status-stream client does not handle CRLF framing and leaks a stream on each reconnect call.

Activity

  1. jeonghun-jj-lee commented on Oct 13, 2026

    @jeonghun-jj-lee
    ContributorAuthor

    Merged into the #1770 integration branch as aef761a (PR #1781, draft). Both readers are now linear: a 10 MB frame in 64 KB chunks splits at a chunked/whole ratio of median 1.037 (relay) and 1.043 (app) against a 3× threshold — the tip's code measured 17.75× and 23.24×. Director gates: tsc 0, suite 323/5498/0/53, relay + app tests 0 failures in 20 runs each, drift PASS, overlay typecheck clean, app full sweep 0 new failures. Also fixes a latent bug: the relay previously never split CRLF upstream frames at all. The SDK reader overlay changes only its buffer block; #1777's cursor contract is byte-identical.

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

Metadata

Metadata

Labels

afkImplementable without human interactionarea:nodearea:webviewbugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions