1package wire
2
3import (
4 "bytes"
5 "testing"
6
7 "google.golang.org/protobuf/proto"
8
9 "github.com/bnema/vev/internal/domain"
10 "github.com/bnema/vev/internal/protocol"
11)
12
13// Baseline Protobuf envelope benchmarks frozen at the P3.3 cutover. They
14// exercise representative control, Hello, Output, and image envelopes so
15// AC8 can compare equivalent QUIC-carried microbenchmarks after P6. The
16// recorded V0 legacy-codec medians live in docs/protocol.md; these
17// benchmarks measure the same conversations through the new envelopes.
18
19func baselineHello() protocol.Hello {
20 return protocol.Hello{
21 Version: protocol.Version, Intent: protocol.IntentAttach,
22 ClientID: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
23 Name: "work",
24 Size: domain.Size{Cols: 120, Rows: 40},
25 TermEnv: "xterm-256color",
26 Cwd: "/tmp/project",
27 TrueColor: true,
28 MaxOutputInFlight: 8,
29 }
30}
31
32func baselineViewContext() *protocol.ViewContext {
33 return &protocol.ViewContext{
34 Publication: 1,
35 Route: protocol.CommittedRouteIdentity{Target: protocol.ExactSessionTarget{LifecycleID: domain.SessionLifecycleID{1}, SessionName: "work"}},
36 TabID: "tab-1", FocusedPaneID: "pane-1",
37 }
38}
39
40func BenchmarkHelloEnvelope(b *testing.B) {
41 hello := baselineHello()
42 converted := &Hello{
43 Version: uint32(hello.Version),
44 Intent: uint32(hello.Intent),
45 ClientId: append([]byte(nil), hello.ClientID[:]...),
46 Name: hello.Name,
47 Cols: uint32(hello.Size.Cols),
48 Rows: uint32(hello.Size.Rows),
49 TermEnv: hello.TermEnv,
50 Cwd: hello.Cwd,
51 TrueColor: hello.TrueColor,
52 MaxOutputInFlight: uint32(hello.MaxOutputInFlight),
53 }
54 b.ReportAllocs()
55 for range b.N {
56 payload, err := proto.MarshalOptions{Deterministic: true}.Marshal(&ClientEnvelope{
57 Payload: &ClientEnvelope_Hello{Hello: converted},
58 })
59 if payload == nil || err != nil {
60 b.Fatalf("marshal hello: %v", err)
61 }
62 }
63}
64
65func BenchmarkHelloEnvelopeUnmarshal(b *testing.B) {
66 converted := &Hello{Version: uint32(protocol.Version), Intent: uint32(protocol.IntentAttach)}
67 payload, err := proto.MarshalOptions{Deterministic: true}.Marshal(&ClientEnvelope{
68 Payload: &ClientEnvelope_Hello{Hello: converted},
69 })
70 if err != nil {
71 b.Fatal(err)
72 }
73 b.ReportAllocs()
74 b.SetBytes(int64(len(payload)))
75 for range b.N {
76 decoded := &ClientEnvelope{}
77 if err := ScanEnvelope(decoded, payload); err != nil {
78 b.Fatal(err)
79 }
80 if uerr := (proto.UnmarshalOptions{DiscardUnknown: false}.Unmarshal(payload, decoded)); uerr != nil {
81 b.Fatal(err)
82 }
83 }
84}
85
86func BenchmarkInputEnvelopeRoundTrip(b *testing.B) {
87 data := []byte("ls -la\r")
88 converted := &Input{InputSeq: 1, ActionId: 2, Data: data}
89 b.ReportAllocs()
90 b.SetBytes(int64(len(data)))
91 for range b.N {
92 payload, err := proto.MarshalOptions{Deterministic: true}.Marshal(&ClientEnvelope{
93 Payload: &ClientEnvelope_Input{Input: converted},
94 })
95 if err != nil {
96 b.Fatal(err)
97 }
98 decoded := &ClientEnvelope{}
99 if err := ScanEnvelope(decoded, payload); err != nil {
100 b.Fatal(err)
101 }
102 if uerr := (proto.UnmarshalOptions{DiscardUnknown: false}.Unmarshal(payload, decoded)); uerr != nil {
103 b.Fatal(err)
104 }
105 }
106}
107
108func BenchmarkImageEnvelopeRoundTrip(b *testing.B) {
109 data := bytes.Repeat([]byte{0x89, 0x50, 0x4e, 0x47}, 4096)
110 converted := &ImagePush{InputSeq: 1, Mime: "image/png", Data: data}
111 payload, err := proto.MarshalOptions{Deterministic: true}.Marshal(&ClientEnvelope{
112 Payload: &ClientEnvelope_ImagePush{ImagePush: converted},
113 })
114 if err != nil {
115 b.Fatal(err)
116 }
117 b.ReportAllocs()
118 b.SetBytes(int64(len(payload)))
119 for range b.N {
120 decoded := &ClientEnvelope{}
121 if err := ScanEnvelope(decoded, payload); err != nil {
122 b.Fatal(err)
123 }
124 if uerr := (proto.UnmarshalOptions{DiscardUnknown: false}.Unmarshal(payload, decoded)); uerr != nil {
125 b.Fatal(err)
126 }
127 }
128}
129
130func baselineOutputData(compressible bool) []byte {
131 if compressible {
132 return bytes.Repeat([]byte("\x1b[38;2;120;180;240mstyled viewport row\x1b[0m\r\n"), 128)
133 }
134 return bytes.Repeat([]byte("0123456789abcdef"), 512)
135}
136
137func baselineOutputEnvelope(compressible bool) []byte {
138 context := baselineViewContext()
139 converted := &Output{
140 Epoch: 1, NewState: 1, Cols: 120, Rows: 40, Full: true,
141 Context: &ViewContext{
142 Publication: context.Publication,
143 Route: &CommittedRouteIdentity{Target: &ExactTarget{SessionName: "work"}},
144 TabId: string(context.TabID),
145 FocusedPaneId: string(context.FocusedPaneID),
146 },
147 Encoding: 0,
148 UncompressedLength: uint64(len(baselineOutputData(compressible))),
149 Data: baselineOutputData(compressible),
150 }
151 payload, err := proto.MarshalOptions{Deterministic: true}.Marshal(&ServerEnvelope{
152 Payload: &ServerEnvelope_Output{Output: converted},
153 })
154 if err != nil {
155 panic(err)
156 }
157 return payload
158}
159
160func BenchmarkOutputCompressibleEnvelopeRoundTrip(b *testing.B) {
161 encoded := baselineOutputEnvelope(true)
162 b.ReportAllocs()
163 b.SetBytes(int64(len(baselineOutputData(true))))
164 for range b.N {
165 decoded := &ServerEnvelope{}
166 if err := ScanEnvelope(decoded, encoded); err != nil {
167 b.Fatal(err)
168 }
169 if uerr := (proto.UnmarshalOptions{DiscardUnknown: false}.Unmarshal(encoded, decoded)); uerr != nil {
170 b.Fatal(uerr)
171 }
172 }
173}
174
175func BenchmarkOutputIncompressibleEnvelopeRoundTrip(b *testing.B) {
176 encoded := baselineOutputEnvelope(false)
177 b.ReportAllocs()
178 b.SetBytes(int64(len(baselineOutputData(false))))
179 for range b.N {
180 decoded := &ServerEnvelope{}
181 if err := ScanEnvelope(decoded, encoded); err != nil {
182 b.Fatal(err)
183 }
184 if uerr := (proto.UnmarshalOptions{DiscardUnknown: false}.Unmarshal(encoded, decoded)); uerr != nil {
185 b.Fatal(uerr)
186 }
187 }
188}