perf: fast-path comparison in ResponseMessage to skip JSON.stringify during streaming (#21884)

ResponseMessage compared the entire message object via JSON.stringify on every reactive tick to detect changes. During streaming, content changes on every token, making the two O(content_length) JSON.stringify calls always return different results — pure wasted work. Add a fast O(1) comparison on content and done fields first. When either differs (the common streaming case), skip straight to cloning. Only fall through to the expensive JSON.stringify comparison for infrequent changes like sources, annotations, or status updates.
This commit is contained in:
Classic298
2026-02-26 14:47:32 -06:00
committed by GitHub
parent 527d36e13a
commit 4654ecbf1b
@@ -121,8 +121,16 @@
let message: MessageType = JSON.parse(JSON.stringify(history.messages[messageId]));
$: if (history.messages) {
if (JSON.stringify(message) !== JSON.stringify(history.messages[messageId])) {
message = JSON.parse(JSON.stringify(history.messages[messageId]));
const source = history.messages[messageId];
if (source) {
// Fast path: O(1) check on the fields that change most often (content during streaming, done at end)
// Avoids 2x O(n) JSON.stringify calls that are always true during streaming anyway
if (message.content !== source.content || message.done !== source.done) {
message = JSON.parse(JSON.stringify(source));
} else if (JSON.stringify(message) !== JSON.stringify(source)) {
// Slow path: full comparison for infrequent changes (sources, annotations, status, etc.)
message = JSON.parse(JSON.stringify(source));
}
}
}