| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- package service
- import (
- "strconv"
- "strings"
- "testing"
- "github.com/Wei-Shaw/sub2api/internal/domain"
- )
- var (
- benchmarkStringSink string
- benchmarkIntSink int
- )
- // BenchmarkGenerateSessionHash_Metadata 关注 JSON 解析与正则匹配开销。
- func BenchmarkGenerateSessionHash_Metadata(b *testing.B) {
- svc := &GatewayService{}
- body := []byte(`{"metadata":{"user_id":"session_123e4567-e89b-12d3-a456-426614174000"},"messages":[{"content":"hello"}]}`)
- b.ReportAllocs()
- for i := 0; i < b.N; i++ {
- parsed, err := ParseGatewayRequest(NewRequestBodyRef(body), "")
- if err != nil {
- b.Fatalf("解析请求失败: %v", err)
- }
- benchmarkStringSink = svc.GenerateSessionHash(parsed)
- }
- }
- func BenchmarkParseGatewayRequest_LargeAnthropicMessages(b *testing.B) {
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeAnthropicMessagesBody(size.bytes, false)
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- parsed, err := ParseGatewayRequest(NewRequestBodyRef(body), domain.PlatformAnthropic)
- if err != nil {
- b.Fatalf("解析 Anthropic 请求失败: %v", err)
- }
- benchmarkIntSink = len(parsed.MessagesRaw())
- }
- })
- }
- }
- func BenchmarkParseGatewayRequest_LargeGeminiContents(b *testing.B) {
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeGeminiContentsBody(size.bytes)
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- parsed, err := ParseGatewayRequest(NewRequestBodyRef(body), domain.PlatformGemini)
- if err != nil {
- b.Fatalf("解析 Gemini 请求失败: %v", err)
- }
- benchmarkIntSink = len(parsed.MessagesRaw())
- }
- })
- }
- }
- func BenchmarkGenerateSessionHash_LargeAnthropicMessages(b *testing.B) {
- svc := &GatewayService{}
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeAnthropicMessagesBody(size.bytes, true)
- parsed, err := ParseGatewayRequest(NewRequestBodyRef(body), domain.PlatformAnthropic)
- if err != nil {
- b.Fatalf("解析请求失败: %v", err)
- }
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- benchmarkStringSink = svc.GenerateSessionHash(parsed)
- }
- })
- }
- }
- func BenchmarkOpenAIResponses_LargeInputMeta(b *testing.B) {
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeOpenAIResponsesBody(size.bytes)
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- model, stream, promptCacheKey := extractOpenAIRequestMetaFromBody(body)
- benchmarkStringSink = model + promptCacheKey
- if stream {
- benchmarkIntSink++
- }
- }
- })
- }
- }
- func BenchmarkOpenAIResponses_LargeInputDecodeMap(b *testing.B) {
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeOpenAIResponsesBody(size.bytes)
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- reqBody, err := getOpenAIRequestBodyMap(nil, body)
- if err != nil {
- b.Fatalf("解析 OpenAI 请求失败: %v", err)
- }
- benchmarkIntSink = len(reqBody)
- }
- })
- }
- }
- func BenchmarkOpenAIResponses_LargeInputRawPatch(b *testing.B) {
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeOpenAIResponsesBody(size.bytes)
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- view := newOpenAIRequestView(body)
- view.MarkPatchSet("instructions", "You are a helpful coding assistant.")
- view.MarkPatchSet("reasoning.effort", "none")
- patched, err := view.ApplyPatches()
- if err != nil {
- b.Fatalf("应用 OpenAI raw patch 失败: %v", err)
- }
- benchmarkIntSink = len(patched)
- }
- })
- }
- }
- func BenchmarkOpenAIResponses_LargeInputImageBillingRaw(b *testing.B) {
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeOpenAIResponsesImageToolBody(size.bytes)
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- cfg, err := resolveOpenAIResponsesImageBillingConfigDetailedFromBody(body, "gpt-5.4")
- if err != nil {
- b.Fatalf("解析 OpenAI 图片计费配置失败: %v", err)
- }
- benchmarkStringSink = cfg.Model + cfg.SizeTier + cfg.InputSize
- }
- })
- }
- }
- func BenchmarkOpenAIResponses_LargeInputEmptyBase64Guard(b *testing.B) {
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeOpenAIResponsesBody(size.bytes)
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if openAIRequestBodyMayContainEmptyBase64InputImage(body) {
- benchmarkIntSink++
- }
- }
- })
- }
- }
- func BenchmarkOpenAIResponses_LargeInputFunctionCallValidation(b *testing.B) {
- for _, size := range benchmarkBodySizes() {
- b.Run(size.name, func(b *testing.B) {
- body := buildLargeOpenAIResponsesToolContinuationBody(size.bytes)
- b.SetBytes(int64(len(body)))
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- validation := ValidateFunctionCallOutputContextBytes(body)
- if !validation.HasFunctionCallOutput || !validation.HasItemReferenceForAllCallIDs {
- b.Fatalf("工具续链校验结果异常: %+v", validation)
- }
- benchmarkIntSink++
- }
- })
- }
- }
- // BenchmarkExtractCacheableContent_System 关注字符串拼接路径的性能。
- func BenchmarkExtractCacheableContent_System(b *testing.B) {
- svc := &GatewayService{}
- req := buildSystemCacheableRequest(12)
- b.ReportAllocs()
- for i := 0; i < b.N; i++ {
- benchmarkStringSink = svc.extractCacheableContent(req)
- }
- }
- func benchmarkBodySizes() []struct {
- name string
- bytes int
- } {
- return []struct {
- name string
- bytes int
- }{
- {name: "4MB", bytes: 4 << 20},
- {name: "8MB", bytes: 8 << 20},
- {name: "16MB", bytes: 16 << 20},
- {name: "32MB", bytes: 32 << 20},
- }
- }
- func buildSystemCacheableRequest(parts int) *ParsedRequest {
- var builder strings.Builder
- _, _ = builder.WriteString(`{"system":[`)
- for i := 0; i < parts; i++ {
- if i > 0 {
- _ = builder.WriteByte(',')
- }
- _, _ = builder.WriteString(`{"text":"system_part_`)
- _, _ = builder.WriteString(strconv.Itoa(i))
- _, _ = builder.WriteString(`","cache_control":{"type":"ephemeral"}}`)
- }
- _, _ = builder.WriteString(`]}`)
- parsed, err := ParseGatewayRequest(NewRequestBodyRef([]byte(builder.String())), "")
- if err != nil {
- panic(err)
- }
- return parsed
- }
- func buildLargeAnthropicMessagesBody(targetBytes int, includeCacheControl bool) []byte {
- var builder strings.Builder
- builder.Grow(targetBytes + 1024)
- _, _ = builder.WriteString(`{"model":"claude-sonnet-4-5","stream":true,"system":[{"type":"text","text":"system seed"}],"messages":[`)
- for i := 0; builder.Len() < targetBytes; i++ {
- if i > 0 {
- _ = builder.WriteByte(',')
- }
- _, _ = builder.WriteString(`{"role":"user","content":[{"type":"text","text":"`)
- _, _ = builder.WriteString(strings.Repeat("anthropic payload ", 64))
- _, _ = builder.WriteString(strconv.Itoa(i))
- _ = builder.WriteByte('"')
- if includeCacheControl && i%32 == 0 {
- _, _ = builder.WriteString(`,"cache_control":{"type":"ephemeral"}`)
- }
- _, _ = builder.WriteString(`}]}`)
- }
- _, _ = builder.WriteString(`]}`)
- return []byte(builder.String())
- }
- func buildLargeGeminiContentsBody(targetBytes int) []byte {
- var builder strings.Builder
- builder.Grow(targetBytes + 1024)
- _, _ = builder.WriteString(`{"model":"gemini-2.5-pro","systemInstruction":{"parts":[{"text":"system seed"}]},"contents":[`)
- for i := 0; builder.Len() < targetBytes; i++ {
- if i > 0 {
- _ = builder.WriteByte(',')
- }
- _, _ = builder.WriteString(`{"role":"user","parts":[{"text":"`)
- _, _ = builder.WriteString(strings.Repeat("gemini payload ", 64))
- _, _ = builder.WriteString(strconv.Itoa(i))
- _, _ = builder.WriteString(`"}]}`)
- }
- _, _ = builder.WriteString(`]}`)
- return []byte(builder.String())
- }
- func buildLargeOpenAIResponsesBody(targetBytes int) []byte {
- var builder strings.Builder
- builder.Grow(targetBytes + 1024)
- _, _ = builder.WriteString(`{"model":"gpt-5.4","stream":true,"prompt_cache_key":"session-benchmark","input":[`)
- for i := 0; builder.Len() < targetBytes; i++ {
- if i > 0 {
- _ = builder.WriteByte(',')
- }
- _, _ = builder.WriteString(`{"type":"message","role":"user","content":[{"type":"input_text","text":"`)
- _, _ = builder.WriteString(strings.Repeat("openai responses payload ", 48))
- _, _ = builder.WriteString(strconv.Itoa(i))
- _, _ = builder.WriteString(`"}]}`)
- }
- _, _ = builder.WriteString(`],"tools":[{"type":"function","name":"lookup","parameters":{"type":"object","properties":{"query":{"type":"string"}}}}]}`)
- return []byte(builder.String())
- }
- func buildLargeOpenAIResponsesToolContinuationBody(targetBytes int) []byte {
- var builder strings.Builder
- builder.Grow(targetBytes + 1024)
- _, _ = builder.WriteString(`{"model":"gpt-5.4","stream":true,"previous_response_id":"resp_benchmark","input":[`)
- for i := 0; builder.Len() < targetBytes; i++ {
- if i > 0 {
- _ = builder.WriteByte(',')
- }
- callID := "call_" + strconv.Itoa(i)
- _, _ = builder.WriteString(`{"type":"item_reference","id":"`)
- _, _ = builder.WriteString(callID)
- _, _ = builder.WriteString(`"},{"type":"function_call_output","call_id":"`)
- _, _ = builder.WriteString(callID)
- _, _ = builder.WriteString(`","output":"`)
- _, _ = builder.WriteString(strings.Repeat("tool output payload ", 48))
- _, _ = builder.WriteString(strconv.Itoa(i))
- _, _ = builder.WriteString(`"}`)
- }
- _, _ = builder.WriteString(`]}`)
- return []byte(builder.String())
- }
- func buildLargeOpenAIResponsesImageToolBody(targetBytes int) []byte {
- var builder strings.Builder
- builder.Grow(targetBytes + 1024)
- _, _ = builder.WriteString(`{"model":"gpt-5.4","stream":false,"tools":[{"type":"image_generation","model":"gpt-image-2","size":"2048x1152"}],"input":[`)
- for i := 0; builder.Len() < targetBytes; i++ {
- if i > 0 {
- _ = builder.WriteByte(',')
- }
- _, _ = builder.WriteString(`{"type":"message","role":"user","content":[{"type":"input_text","text":"`)
- _, _ = builder.WriteString(strings.Repeat("openai image billing payload ", 48))
- _, _ = builder.WriteString(strconv.Itoa(i))
- _, _ = builder.WriteString(`"}]}`)
- }
- _, _ = builder.WriteString(`]}`)
- return []byte(builder.String())
- }
|