Skip to content

fix: remove quadratic router payload processing - #1326

Merged
makosblade merged 3 commits into
mainfrom
fix/linear-payload-processing
Sep 15, 2026
Merged

makosblade merged 3 commits into
mainfrom
fix/linear-payload-processing

Conversation

@makosblade

@makosblade makosblade commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Problem

Four request-processing paths did repeated work proportional to payload size, so cost grew quadratically:

  • Tool-argument repair re-serialized the whole JSON document on every edit (SJSON). 16,384 coercions took 4.75 s; 16,384 duplicate-key deletions took 181 ms.
  • SSE framing re-scanned the buffer from byte 0 on every write. A 1 MiB frame arriving in 4 KiB chunks took 3.3 ms of pure scanning.
  • Responses history cleanup (stripping our badge/footer before re-sending to OpenAI) rebuilt the input array per message. 1,024 messages took 117–161 ms.
  • Escalation assembly rebuilt text/tool-call strings per streamed fragment.

An earlier version of this PR fixed the speed but introduced two behavior regressions (nested-union repairs lost edits; empty assistant shells stopped being dropped) and left member lookup quadratic.

Solution

  • sse.Scanner: a per-buffer cursor that resumes the delimiter search where the last write left off. Zero-alloc, same LF/CRLF grammar. Wired into all 18 buffered consumers with their existing reset/EOF semantics.
  • Tool arguments: an ordered, lazily-indexed edit tree. Single small edits still use the original GJSON/SJSON path; a second edit builds a per-object key index so lookups stop scanning siblings. Array wrapping preserves child edits.
  • Responses cleanup: single pass, restores dropping already-empty assistant text shells.
  • Escalation: retained builders; benchmarks now exercise real growing fragments instead of no-ops.

Impact

Medians of 10 runs, base vs this branch, Apple M4 Pro.

Nominal request sizes (what most traffic looks like):

Path Input Base Fixed
Tool args, 1–8 fields repaired typical tool call 1–16 µs 1–20 µs (0.8–0.9×)
Tool args, clean input, any size no repair needed 47 ns–301 µs +4%, still 0 allocs
Tool args, 128 fields repaired large structured call 76–495 µs 28–220 µs (2.2–2.7×)
SSE, 64 KiB frame in 4 KiB writes big tool result / long delta 139 µs 19 µs (7×)
SSE, small frames, 64-byte writes normal streaming 63 µs 29 µs (2×)
Responses cleanup, 128 msgs w/ badge Codex session history 2.3 ms 190 µs (12×)
Responses cleanup, nothing to strip non-Weave history 51 µs 53 µs (parity)
Escalation, 2,048 fragments long tool-heavy turn 3.3–12.2 ms 1.5–5.0 ms

Large inputs (the quadratic cases): tool-arg repair 36–134× faster at 16k fields; SSE 13× at 1 MiB; Responses cleanup 84–178× at 1k messages.

The one cost: tiny repairs (1–8 fields) pay ~1–3 µs of index setup. Everything else is neutral or faster.

Verification

  • 15,766-case public-API corpus: zero differences from base (the earlier revision had 26).
  • Full test suite, race suite, vet, lint; 3 fuzz targets × 60 s with seeds committed.
  • 46-case SSE matrix: no case slower than base. Translation/escalation outliers re-checked with alternating run order; none reproduced.
  • Weave checks: 18/19 pass; the diagnostic-logging findings are on pure JSON helpers with no external calls and were declined per that check's scope exclusion.

Local Docker was unavailable, so replay-smoke relies on CI.

🤖 Generated with Weave Router

Comment thread internal/translate/toolcheck/arguments.go Fixed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread internal/translate/toolcheck/arguments.go
@greptile-apps

greptile-apps Bot commented Sep 15, 2026

Copy link
Copy Markdown

Retrigger

The PR is not yet safe to merge because valid colon-prefixed schema properties can no longer receive deterministic argument repairs.

Reviews (1) · Last reviewed commit: "Remove quadratic router payload processi..."

Comment thread internal/translate/toolcheck/arguments.go Outdated
Comment thread internal/translate/toolcheck/arguments.go Outdated
@makosblade makosblade changed the title fix/linear payload processing fix: remove quadratic router payload processing Sep 15, 2026
@makosblade
makosblade force-pushed the fix/linear-payload-processing branch from e7f258a to 20325d6 Compare September 15, 2026 19:54

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 20325d6. Configure here.

Comment thread internal/translate/toolcheck/repair.go
@makosblade
makosblade force-pushed the fix/linear-payload-processing branch from 953cabe to 43f5096 Compare September 15, 2026 22:54
@makosblade
makosblade force-pushed the fix/linear-payload-processing branch from 43f5096 to 8100c95 Compare September 15, 2026 23:01
@makosblade
makosblade merged commit 4fee06f into main Sep 15, 2026
21 checks passed
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.

2 participants