Skip to content

perf(mcp): Copy tool output on write when replacing lone surrogates - #1798

Merged
BYK merged 1 commit into
mainfrom
perf/mcp-well-formed-copy-on-write
Nov 2, 2026
Merged

BYK merged 1 commit into
mainfrom
perf/mcp-well-formed-copy-on-write

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #1790. toWellFormedOutput runs on every tool response, and it rebuilt every array (map) and object (Object.entries → map → Object.fromEntries), even when there was nothing to replace. Almost no response contains a lone surrogate, so nearly all of that copying was wasted.

It now copies on write. It returns the input unchanged unless a string or key actually changes, and then copies only the arrays and objects on the path to that string. Objects are walked with for...in + Object.hasOwn, so the common path allocates nothing. Output is the same as before.

Benchmark

Node 22.23, median time per call and bytes allocated per call (large semi-space so no GC runs inside the measured loop). "Structured" rows are issue-shaped objects with 12 fields, a nested project object, and a tags array.

payload before (#1790) after JSON.stringify for scale
string, 45 KB 52 µs / ~0 B 52 µs / ~0 B 229 µs
content[], 1 × 45 KB text 53 µs / 0.6 KB 52 µs / ~0 B 176 µs
structured, 50 rows 376 µs / 210 KB 42 µs / ~0 B 89 µs
structured, 500 rows 2.37 ms / 1.9 MB 425 µs / ~0 B 1.58 ms
structured, 500 rows + 1 lone surrogate 2.16 ms / 1.9 MB 451 µs / 7.4 KB 1.28 ms
string, 45 KB + lone surrogate 107 µs / 123 KB 109 µs / 123 KB 163 µs
  • On structured output it is about 5× faster and allocates almost nothing; before, it allocated about 1.5× the payload size on every call.
  • String-only and content[] output was already cheap. V8 returns the same string from toWellFormed() when the string is well formed, so most of the time left is the scan itself, which can't be skipped.
  • I also tried running JSON.stringify once and walking only when the JSON contains a \uD8xx–\uDFxx escape. It was slower than the walk in every case, so it isn't used.

Tests

The structured case in server.test.ts now has a lone surrogate inside a nested array, next to strings that don't change. That covers the partial-copy path; if the copy drops the entries before the changed one, the test fails.

via @BYK.

--

View Session in Sentry

toWellFormedOutput rebuilt every array and object in every tool response,
even when nothing needed replacing. Return the input as-is unless a string
or key changes, and copy only the containers on the path to it.

Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
@vercel

vercel Bot commented Nov 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
sentry-local Skipped Skipped Nov 2, 2026 12:26pm UTC

Request Review

@github-actions github-actions Bot added the risk: medium PR risk score: medium label Nov 2, 2026
@BYK
BYK enabled auto-merge (squash) November 2, 2026 12:31
@BYK
BYK merged commit 85af9ea into main Nov 2, 2026
33 checks passed
@BYK
BYK deleted the perf/mcp-well-formed-copy-on-write branch November 2, 2026 12:40

This branch was previously deployed

1 inactive deployment
Preview — e8601c76 Deployed Nov 2, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant