返回 DeepSeek-Reasonix
history_perf_test.go
根目录 / desktop / history_perf_test.go
1 package main
2
3 import (
4 "encoding/json"
5 "fmt"
6 "strings"
7 "testing"
8
9 "reasonix/internal/provider"
10 )
11
12 type historyPerfCase struct {
13 name string
14 turns int
15 outputSize int
16 toolName string
17 failed bool
18 }
19
20 func syntheticHistoryMessages(turns, outputSize int, toolName string, failed bool) []provider.Message {
21 msgs := make([]provider.Message, 0, turns*4)
22 output := strings.Repeat("x", outputSize)
23 if failed {
24 output = "error: " + output
25 }
26 for i := 0; i < turns; i++ {
27 callID := fmt.Sprintf("call_%d", i)
28 msgs = append(msgs,
29 provider.Message{Role: provider.RoleUser, Content: fmt.Sprintf("prompt %d", i)},
30 provider.Message{
31 Role: provider.RoleAssistant,
32 Content: fmt.Sprintf("answer %d", i),
33 ToolCalls: []provider.ToolCall{{
34 ID: callID,
35 Name: toolName,
36 Arguments: fmt.Sprintf(`{"command":"synthetic-%d","path":"file-%d.txt"}`, i, i),
37 }},
38 },
39 provider.Message{
40 Role: provider.RoleTool,
41 Name: toolName,
42 ToolCallID: callID,
43 Content: output,
44 },
45 )
46 }
47 return msgs
48 }
49
50 func historyPerfCases() []historyPerfCase {
51 return []historyPerfCase{
52 {name: "50x1MB-bash-success", turns: 50, outputSize: 1 << 20, toolName: "bash"},
53 {name: "200x100KB-bash-success", turns: 200, outputSize: 100 << 10, toolName: "bash"},
54 {name: "1000x10KB-bash-success", turns: 1000, outputSize: 10 << 10, toolName: "bash"},
55 {name: "20x5MB-bash-success", turns: 20, outputSize: 5 << 20, toolName: "bash"},
56 {name: "50x1MB-read-success", turns: 50, outputSize: 1 << 20, toolName: "read_file"},
57 {name: "50x1MB-bash-error", turns: 50, outputSize: 1 << 20, toolName: "bash", failed: true},
58 }
59 }
60
61 func BenchmarkHistoryMessagesSynthetic(b *testing.B) {
62 for _, tc := range historyPerfCases() {
63 b.Run(tc.name, func(b *testing.B) {
64 msgs := syntheticHistoryMessages(tc.turns, tc.outputSize, tc.toolName, tc.failed)
65 inputBytes := int64(tc.turns * tc.outputSize)
66 b.ReportAllocs()
67 b.SetBytes(inputBytes)
68 b.ResetTimer()
69 for i := 0; i < b.N; i++ {
70 got := historyMessages(msgs, func(content string) string { return content })
71 if len(got) == 0 {
72 b.Fatal("empty history")
73 }
74 }
75 })
76 }
77 }
78
79 func BenchmarkHistoryMessagesMarshalSynthetic(b *testing.B) {
80 for _, tc := range historyPerfCases() {
81 b.Run(tc.name, func(b *testing.B) {
82 msgs := syntheticHistoryMessages(tc.turns, tc.outputSize, tc.toolName, tc.failed)
83 inputBytes := int64(tc.turns * tc.outputSize)
84 b.ReportAllocs()
85 b.SetBytes(inputBytes)
86 b.ResetTimer()
87 for i := 0; i < b.N; i++ {
88 got := historyMessages(msgs, func(content string) string { return content })
89 encoded, err := json.Marshal(got)
90 if err != nil {
91 b.Fatal(err)
92 }
93 if len(encoded) == 0 {
94 b.Fatal("empty JSON")
95 }
96 }
97 })
98 }
99 }
100
101 func TestHistoryMessagesSyntheticPayloadSizes(t *testing.T) {
102 msgs := syntheticHistoryMessages(10, 1<<20, "bash", false)
103 got := historyMessages(msgs, func(content string) string { return content })
104 encoded, err := json.Marshal(got)
105 if err != nil {
106 t.Fatal(err)
107 }
108 t.Logf("synthetic history payload bytes: %d", len(encoded))
109 }
110
110 lines GO