From 53c1e7e2dd6ddf973098a4e685e852aeebed9fe3 Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Mon, 20 Jul 2026 15:37:55 +0800 Subject: [PATCH] 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. --- .../runtime/executor/helps/payload_helpers.go | 2 +- .../executor/helps/payload_mutations.go | 2 +- .../executor/helps/payload_mutations_test.go | 32 +++++++++++++++++++ .../executor/helps/vertex_payload_helpers.go | 3 +- internal/runtime/executor/kimi_executor.go | 2 +- internal/signature/gemini_sanitize.go | 3 +- internal/util/gjson.go | 16 ++++++++++ internal/util/gjson_test.go | 17 ++++++++++ 8 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 internal/util/gjson.go create mode 100644 internal/util/gjson_test.go diff --git a/internal/runtime/executor/helps/payload_helpers.go b/internal/runtime/executor/helps/payload_helpers.go index bb18f4151..e50dd3233 100644 --- a/internal/runtime/executor/helps/payload_helpers.go +++ b/internal/runtime/executor/helps/payload_helpers.go @@ -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)) diff --git a/internal/runtime/executor/helps/payload_mutations.go b/internal/runtime/executor/helps/payload_mutations.go index fc48f38cd..7896d9b2f 100644 --- a/internal/runtime/executor/helps/payload_mutations.go +++ b/internal/runtime/executor/helps/payload_mutations.go @@ -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) diff --git a/internal/runtime/executor/helps/payload_mutations_test.go b/internal/runtime/executor/helps/payload_mutations_test.go index e96aa3900..36009d2cd 100644 --- a/internal/runtime/executor/helps/payload_mutations_test.go +++ b/internal/runtime/executor/helps/payload_mutations_test.go @@ -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{{ diff --git a/internal/runtime/executor/helps/vertex_payload_helpers.go b/internal/runtime/executor/helps/vertex_payload_helpers.go index 2b2c46244..b4422da56 100644 --- a/internal/runtime/executor/helps/vertex_payload_helpers.go +++ b/internal/runtime/executor/helps/vertex_payload_helpers.go @@ -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 } diff --git a/internal/runtime/executor/kimi_executor.go b/internal/runtime/executor/kimi_executor.go index 1799e6652..7f67d3d2c 100644 --- a/internal/runtime/executor/kimi_executor.go +++ b/internal/runtime/executor/kimi_executor.go @@ -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 } diff --git a/internal/signature/gemini_sanitize.go b/internal/signature/gemini_sanitize.go index 9678c46d2..4fefc1d4d 100644 --- a/internal/signature/gemini_sanitize.go +++ b/internal/signature/gemini_sanitize.go @@ -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 } diff --git a/internal/util/gjson.go b/internal/util/gjson.go new file mode 100644 index 000000000..cd6fd7c75 --- /dev/null +++ b/internal/util/gjson.go @@ -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) +} diff --git a/internal/util/gjson_test.go b/internal/util/gjson_test.go new file mode 100644 index 000000000..8ce36958c --- /dev/null +++ b/internal/util/gjson_test.go @@ -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) + } +}