perf(stream): append text deltas as JSON without an intermediate Marshal

This commit is contained in:
2026-09-29 12:26:15 +01:00
parent baabd5d3bb
commit 2cd686a669
2 changed files with 77 additions and 6 deletions
+60 -6
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"strconv"
"strings"
"unicode/utf8"
)
// anthropicAPIVersion is the "anthropic-version" header value every request
@@ -776,16 +777,69 @@ func (c *contentChunker) set(id, model string, created int64) {
}
func (c *contentChunker) build(text string) []byte {
tb, err := json.Marshal(text)
if err != nil {
panic(fmt.Sprintf("llmgateway: stream chunk failed to marshal text: %v", err))
}
out := make([]byte, 0, len(contentChunkHead)+len(tb)+len(c.tail))
out := make([]byte, 0, len(contentChunkHead)+len(text)+len(text)/8+2+len(c.tail))
out = append(out, contentChunkHead...)
out = append(out, tb...)
out = appendJSONString(out, text)
return append(out, c.tail...)
}
const jsonHex = "0123456789abcdef"
// appendJSONString appends s as a quoted JSON string using
// encoding/json's default escaping (HTML characters, U+2028/U+2029 and
// invalid UTF-8 included), so its output equals json.Marshal(s).
func appendJSONString(dst []byte, s string) []byte {
dst = append(dst, '"')
start := 0
for i := 0; i < len(s); {
b := s[i]
if b < utf8.RuneSelf {
if b >= 0x20 && b != '"' && b != '\\' && b != '<' && b != '>' && b != '&' {
i++
continue
}
dst = append(dst, s[start:i]...)
switch b {
case '"', '\\':
dst = append(dst, '\\', b)
case '\b':
dst = append(dst, '\\', 'b')
case '\f':
dst = append(dst, '\\', 'f')
case '\n':
dst = append(dst, '\\', 'n')
case '\r':
dst = append(dst, '\\', 'r')
case '\t':
dst = append(dst, '\\', 't')
default:
dst = append(dst, '\\', 'u', '0', '0', jsonHex[b>>4], jsonHex[b&0xF])
}
i++
start = i
continue
}
r, size := utf8.DecodeRuneInString(s[i:])
if r == utf8.RuneError && size == 1 {
dst = append(dst, s[start:i]...)
dst = append(dst, "\xef\xbf\xbd"...)
i += size
start = i
continue
}
if r == '\u2028' || r == '\u2029' {
dst = append(dst, s[start:i]...)
dst = append(dst, '\\', 'u', '2', '0', '2', jsonHex[r&0xF])
i += size
start = i
continue
}
i += size
}
dst = append(dst, s[start:]...)
return append(dst, '"')
}
// usageChunk builds the final usage-only "chat.completion.chunk" payload —
// empty "choices" plus a populated "usage" — mirroring the shape
// provider_openai.go's forwardStream relays from a native OpenAI upstream
+17
View File
@@ -1150,3 +1150,20 @@ func TestContentChunkerMatchesChunk(t *testing.T) {
}
}
}
func TestAppendJSONStringMatchesMarshal(t *testing.T) {
var cases []string
for r := rune(0); r < 0x250; r++ {
cases = append(cases, string(r), "a"+string(r)+"b")
}
cases = append(cases, "\u2028", "\u2029", "x\u2028y\u2029z", "bad\xffutf8", "\xc3", "\xe2\x80", "\U0001F600 emoji", "", "<script>alert('&')</script>")
for _, s := range cases {
want, err := json.Marshal(s)
if err != nil {
t.Fatalf("Marshal(%q): %v", s, err)
}
if got := appendJSONString(nil, s); !bytes.Equal(got, want) {
t.Errorf("appendJSONString(%q) = %s, want %s", s, got, want)
}
}
}