Skip to content

perf(ai): speed up partial JSON streaming by 20-27% by skipping a parse that always fails - #23461

Open
deadstrobe5 wants to merge 1 commit into
vercel:mainfrom
deadstrobe5:perf-partial-json-skip-parse
Open

deadstrobe5 wants to merge 1 commit into
vercel:mainfrom
deadstrobe5:perf-partial-json-skip-parse

Conversation

@deadstrobe5

Copy link
Copy Markdown

Background

parsePartialJson runs on every delta of streamText with Output.object, of streamObject, and on every tool-input-delta in processUIMessageStream (so every useChat tool call). It starts with JSON.parse on the whole accumulated text. While streaming, that text almost always ends inside an unclosed string, object or array, so this parse fails, builds a JSONParseError, and only then does fixJson run and the repaired text get parsed again.

Summary

fixJson already tracks the parser state, so this adds repairJson, which also returns isTruncated. When it is set, parsePartialJson skips the parse that is bound to fail. The results do not change. A differential test compared old and new on every prefix of 613 random, pretty-printed and mutated documents (28,305 inputs), and every result matched.

End-to-End Verification

Full streamText / readUIMessageStream pipelines with a mock model streaming 8-char deltas, Node 26. Each run is a separate process, 5 runs per side:

scenario before after
streamText + Output.object, 20 KB 296.6 ms 217.6 ms
readUIMessageStream tool input, 20 KB 404.7 ms 323.0 ms
streamText + Output.object, 50 KB 1722 ms 1292 ms

Checklist

  • All commits are signed (PRs with unsigned commits cannot be merged)
  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

Future Work

processUIMessageStream also structuredClones the message on every chunk, which is the next per-chunk cost on the useChat path.

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant