perf(util): introduce GetGJSONBytesNoCopy for efficient JSON parsing without data duplication

- Added `GetGJSONBytesNoCopy` in `internal/util` for safe, no-copy JSON parse operations leveraging `unsafe`.
- Replaced `gjson.GetBytes` with the new helper in key payload processing paths (`kimi_executor`, `vertex_payload_helpers`, etc.) to improve performance.
- Added unit tests for behavior validation, including edge cases with empty input.
This commit is contained in:
Luis Pater
2026-07-20 15:37:55 +08:00
parent 8b4fd28c95
commit 53c1e7e2dd
8 changed files with 72 additions and 5 deletions

View File

@@ -832,7 +832,7 @@ func setPayloadValueIfDifferent(payload []byte, path string, value any) []byte {
if expected.Raw == "" {
return payload
}
if current.Raw == expected.Raw {
if len(current.Indexes) == 0 && current.Raw == expected.Raw {
return payload
}
updated, errSet := sjson.SetRawBytes(payload, path, []byte(expected.Raw))

View File

@@ -36,7 +36,7 @@ func SetBoolIfDifferent(payload []byte, path string, value bool) []byte {
// SetRawIfDifferent updates path only when the existing raw JSON is identical.
func SetRawIfDifferent(payload []byte, path string, value []byte) []byte {
current := gjson.GetBytes(payload, path)
if current.Exists() && current.Raw == string(value) {
if current.Exists() && len(current.Indexes) == 0 && current.Raw == string(value) {
return payload
}
updated, errSet := sjson.SetRawBytes(payload, path, value)

View File

@@ -92,6 +92,38 @@ func TestApplyPayloadConfigReusesCanonicalOverrides(t *testing.T) {
}
}
func TestApplyPayloadConfigProjectionOverrideWritesEveryMatch(t *testing.T) {
cfg := &config.Config{Payload: config.PayloadConfig{
Override: []config.PayloadRule{{
Models: []config.PayloadModelRule{{Name: "gpt-test", Protocol: "openai"}},
Params: map[string]any{"items.#.value": []any{1, 2}},
}},
}}
input := []byte(`{"items":[{"value":1},{"value":2}]}`)
output := ApplyPayloadConfigWithRoot(cfg, "gpt-test", "openai", "", input, nil, "", "")
for _, path := range []string{"items.0.value", "items.1.value"} {
if got := gjson.GetBytes(output, path).Raw; got != `[1,2]` {
t.Fatalf("%s = %s, want [1,2]", path, got)
}
}
}
func TestApplyPayloadConfigProjectionOverrideRawWritesEveryMatch(t *testing.T) {
cfg := &config.Config{Payload: config.PayloadConfig{
OverrideRaw: []config.PayloadRule{{
Models: []config.PayloadModelRule{{Name: "gpt-test", Protocol: "openai"}},
Params: map[string]any{"items.#.value": `[1,2]`},
}},
}}
input := []byte(`{"items":[{"value":1},{"value":2}]}`)
output := ApplyPayloadConfigWithRoot(cfg, "gpt-test", "openai", "", input, nil, "", "")
for _, path := range []string{"items.0.value", "items.1.value"} {
if got := gjson.GetBytes(output, path).Raw; got != `[1,2]` {
t.Fatalf("%s = %s, want [1,2]", path, got)
}
}
}
func TestApplyPayloadConfigNormalizesByteSliceOverride(t *testing.T) {
cfg := &config.Config{Payload: config.PayloadConfig{
Override: []config.PayloadRule{{

View File

@@ -3,6 +3,7 @@ package helps
import (
"strings"
"github.com/router-for-me/CLIProxyAPI/v7/internal/util"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
)
@@ -14,7 +15,7 @@ func StripVertexOpenAIResponsesToolCallIDs(payload []byte, sourceFormat string)
return payload
}
contents := gjson.GetBytes(payload, "contents")
contents := util.GetGJSONBytesNoCopy(payload, "contents")
if !contents.IsArray() || !vertexContentsHaveToolCallIDs(contents) {
return payload
}

View File

@@ -344,7 +344,7 @@ func normalizeKimiToolMessageLinks(body []byte) ([]byte, error) {
return body, nil
}
messages := gjson.GetBytes(body, "messages")
messages := util.GetGJSONBytesNoCopy(body, "messages")
if !messages.Exists() || !messages.IsArray() {
return body, nil
}

View File

@@ -3,6 +3,7 @@ package signature
import (
"strings"
"github.com/router-for-me/CLIProxyAPI/v7/internal/util"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
@@ -32,7 +33,7 @@ func SanitizeGeminiRequestThoughtSignatures(payload []byte, contentsPath string)
contentsPath = "contents"
}
contents := gjson.GetBytes(payload, contentsPath)
contents := util.GetGJSONBytesNoCopy(payload, contentsPath)
if !contents.IsArray() || !geminiContentsThoughtSignaturesNeedSanitize(contents) {
return payload
}

16
internal/util/gjson.go Normal file
View File

@@ -0,0 +1,16 @@
package util
import (
"unsafe"
"github.com/tidwall/gjson"
)
// GetGJSONBytesNoCopy returns a GJSON result that may reference data directly.
// Callers must not retain the result or mutate data while using it.
func GetGJSONBytesNoCopy(data []byte, path string) gjson.Result {
if len(data) == 0 {
return gjson.Result{}
}
return gjson.Get(unsafe.String(unsafe.SliceData(data), len(data)), path)
}

View File

@@ -0,0 +1,17 @@
package util
import "testing"
func TestGetGJSONBytesNoCopy(t *testing.T) {
input := []byte(`{"request":{"contents":[{"role":"user"}]}}`)
contents := GetGJSONBytesNoCopy(input, "request.contents")
if !contents.IsArray() || contents.Get("0.role").String() != "user" {
t.Fatalf("request.contents = %s, want user content array", contents.Raw)
}
}
func TestGetGJSONBytesNoCopyEmptyInput(t *testing.T) {
if result := GetGJSONBytesNoCopy(nil, "contents"); result.Exists() {
t.Fatalf("empty input result = %s, want missing", result.Raw)
}
}