Source file
src/encoding/json/v2_bench_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13 package json
14
15 import (
16 "bytes"
17 "io"
18 "strings"
19 "testing"
20
21 "encoding/json/internal/jsontest"
22 )
23
24 type codeResponse struct {
25 Tree *codeNode `json:"tree"`
26 Username string `json:"username"`
27 }
28
29 type codeNode struct {
30 Name string `json:"name"`
31 Kids []*codeNode `json:"kids"`
32 CLWeight float64 `json:"cl_weight"`
33 Touches int `json:"touches"`
34 MinT int64 `json:"min_t"`
35 MaxT int64 `json:"max_t"`
36 MeanT int64 `json:"mean_t"`
37 }
38
39 var codeJSON []byte
40 var codeStruct codeResponse
41
42 func codeInit() {
43 var data []byte
44 for _, entry := range jsontest.Data {
45 if entry.Name == "GolangSource" {
46 data = entry.Data()
47 }
48 }
49 codeJSON = data
50
51 if err := Unmarshal(codeJSON, &codeStruct); err != nil {
52 panic("unmarshal code.json: " + err.Error())
53 }
54
55 var err error
56 if data, err = Marshal(&codeStruct); err != nil {
57 panic("marshal code.json: " + err.Error())
58 }
59
60 if !bytes.Equal(data, codeJSON) {
61 println("different lengths", len(data), len(codeJSON))
62 for i := 0; i < len(data) && i < len(codeJSON); i++ {
63 if data[i] != codeJSON[i] {
64 println("re-marshal: changed at byte", i)
65 println("orig: ", string(codeJSON[i-10:i+10]))
66 println("new: ", string(data[i-10:i+10]))
67 break
68 }
69 }
70 panic("re-marshal code.json: different result")
71 }
72 }
73
74 func BenchmarkCodeEncoder(b *testing.B) {
75 b.ReportAllocs()
76 if codeJSON == nil {
77 b.StopTimer()
78 codeInit()
79 b.StartTimer()
80 }
81 b.RunParallel(func(pb *testing.PB) {
82 enc := NewEncoder(io.Discard)
83 for pb.Next() {
84 if err := enc.Encode(&codeStruct); err != nil {
85 b.Fatalf("Encode error: %v", err)
86 }
87 }
88 })
89 b.SetBytes(int64(len(codeJSON)))
90 }
91
92 func BenchmarkCodeEncoderError(b *testing.B) {
93 b.ReportAllocs()
94 if codeJSON == nil {
95 b.StopTimer()
96 codeInit()
97 b.StartTimer()
98 }
99
100
101 type Dummy struct {
102 Name string
103 Next *Dummy
104 }
105 dummy := Dummy{Name: "Dummy"}
106 dummy.Next = &dummy
107
108 b.RunParallel(func(pb *testing.PB) {
109 enc := NewEncoder(io.Discard)
110 for pb.Next() {
111 if err := enc.Encode(&codeStruct); err != nil {
112 b.Fatalf("Encode error: %v", err)
113 }
114 if _, err := Marshal(dummy); err == nil {
115 b.Fatal("Marshal error: got nil, want non-nil")
116 }
117 }
118 })
119 b.SetBytes(int64(len(codeJSON)))
120 }
121
122 func BenchmarkCodeMarshal(b *testing.B) {
123 b.ReportAllocs()
124 if codeJSON == nil {
125 b.StopTimer()
126 codeInit()
127 b.StartTimer()
128 }
129 b.RunParallel(func(pb *testing.PB) {
130 for pb.Next() {
131 if _, err := Marshal(&codeStruct); err != nil {
132 b.Fatalf("Marshal error: %v", err)
133 }
134 }
135 })
136 b.SetBytes(int64(len(codeJSON)))
137 }
138
139 func BenchmarkCodeMarshalError(b *testing.B) {
140 b.ReportAllocs()
141 if codeJSON == nil {
142 b.StopTimer()
143 codeInit()
144 b.StartTimer()
145 }
146
147
148 type Dummy struct {
149 Name string
150 Next *Dummy
151 }
152 dummy := Dummy{Name: "Dummy"}
153 dummy.Next = &dummy
154
155 b.RunParallel(func(pb *testing.PB) {
156 for pb.Next() {
157 if _, err := Marshal(&codeStruct); err != nil {
158 b.Fatalf("Marshal error: %v", err)
159 }
160 if _, err := Marshal(dummy); err == nil {
161 b.Fatal("Marshal error: got nil, want non-nil")
162 }
163 }
164 })
165 b.SetBytes(int64(len(codeJSON)))
166 }
167
168 func benchMarshalBytes(n int) func(*testing.B) {
169 sample := []byte("hello world")
170
171
172 v := &struct {
173 Bytes []byte
174 }{
175 bytes.Repeat(sample, (n/len(sample))+1)[:n],
176 }
177 return func(b *testing.B) {
178 for i := 0; i < b.N; i++ {
179 if _, err := Marshal(v); err != nil {
180 b.Fatalf("Marshal error: %v", err)
181 }
182 }
183 }
184 }
185
186 func benchMarshalBytesError(n int) func(*testing.B) {
187 sample := []byte("hello world")
188
189
190 v := &struct {
191 Bytes []byte
192 }{
193 bytes.Repeat(sample, (n/len(sample))+1)[:n],
194 }
195
196
197 type Dummy struct {
198 Name string
199 Next *Dummy
200 }
201 dummy := Dummy{Name: "Dummy"}
202 dummy.Next = &dummy
203
204 return func(b *testing.B) {
205 for i := 0; i < b.N; i++ {
206 if _, err := Marshal(v); err != nil {
207 b.Fatalf("Marshal error: %v", err)
208 }
209 if _, err := Marshal(dummy); err == nil {
210 b.Fatal("Marshal error: got nil, want non-nil")
211 }
212 }
213 }
214 }
215
216 func BenchmarkMarshalBytes(b *testing.B) {
217 b.ReportAllocs()
218
219 b.Run("32", benchMarshalBytes(32))
220
221
222 b.Run("256", benchMarshalBytes(256))
223
224 b.Run("4096", benchMarshalBytes(4096))
225 }
226
227 func BenchmarkMarshalBytesError(b *testing.B) {
228 b.ReportAllocs()
229
230 b.Run("32", benchMarshalBytesError(32))
231
232
233 b.Run("256", benchMarshalBytesError(256))
234
235 b.Run("4096", benchMarshalBytesError(4096))
236 }
237
238 func BenchmarkMarshalMap(b *testing.B) {
239 b.ReportAllocs()
240 m := map[string]int{
241 "key3": 3,
242 "key2": 2,
243 "key1": 1,
244 }
245 b.RunParallel(func(pb *testing.PB) {
246 for pb.Next() {
247 if _, err := Marshal(m); err != nil {
248 b.Fatal("Marshal:", err)
249 }
250 }
251 })
252 }
253
254 func BenchmarkCodeDecoder(b *testing.B) {
255 b.ReportAllocs()
256 if codeJSON == nil {
257 b.StopTimer()
258 codeInit()
259 b.StartTimer()
260 }
261 b.RunParallel(func(pb *testing.PB) {
262 var buf bytes.Buffer
263 dec := NewDecoder(&buf)
264 var r codeResponse
265 for pb.Next() {
266 buf.Write(codeJSON)
267
268 buf.WriteByte('\n')
269 buf.WriteByte('\n')
270 buf.WriteByte('\n')
271 if err := dec.Decode(&r); err != nil {
272 b.Fatalf("Decode error: %v", err)
273 }
274 }
275 })
276 b.SetBytes(int64(len(codeJSON)))
277 }
278
279 func BenchmarkUnicodeDecoder(b *testing.B) {
280 b.ReportAllocs()
281 j := []byte(`"\uD83D\uDE01"`)
282 b.SetBytes(int64(len(j)))
283 r := bytes.NewReader(j)
284 dec := NewDecoder(r)
285 var out string
286 b.ResetTimer()
287 for i := 0; i < b.N; i++ {
288 if err := dec.Decode(&out); err != nil {
289 b.Fatalf("Decode error: %v", err)
290 }
291 r.Seek(0, 0)
292 }
293 }
294
295 func BenchmarkDecoderStream(b *testing.B) {
296 b.ReportAllocs()
297 b.StopTimer()
298 var buf bytes.Buffer
299 dec := NewDecoder(&buf)
300 buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n")
301 var x any
302 if err := dec.Decode(&x); err != nil {
303 b.Fatalf("Decode error: %v", err)
304 }
305 ones := strings.Repeat(" 1\n", 300000) + "\n\n\n"
306 b.StartTimer()
307 for i := 0; i < b.N; i++ {
308 if i%300000 == 0 {
309 buf.WriteString(ones)
310 }
311 x = nil
312 switch err := dec.Decode(&x); {
313 case err != nil:
314 b.Fatalf("Decode error: %v", err)
315 case x != 1.0:
316 b.Fatalf("Decode: got %v want 1.0", i)
317 }
318 }
319 }
320
321 func BenchmarkCodeUnmarshal(b *testing.B) {
322 b.ReportAllocs()
323 if codeJSON == nil {
324 b.StopTimer()
325 codeInit()
326 b.StartTimer()
327 }
328 b.RunParallel(func(pb *testing.PB) {
329 for pb.Next() {
330 var r codeResponse
331 if err := Unmarshal(codeJSON, &r); err != nil {
332 b.Fatalf("Unmarshal error: %v", err)
333 }
334 }
335 })
336 b.SetBytes(int64(len(codeJSON)))
337 }
338
339 func BenchmarkCodeUnmarshalReuse(b *testing.B) {
340 b.ReportAllocs()
341 if codeJSON == nil {
342 b.StopTimer()
343 codeInit()
344 b.StartTimer()
345 }
346 b.RunParallel(func(pb *testing.PB) {
347 var r codeResponse
348 for pb.Next() {
349 if err := Unmarshal(codeJSON, &r); err != nil {
350 b.Fatalf("Unmarshal error: %v", err)
351 }
352 }
353 })
354 b.SetBytes(int64(len(codeJSON)))
355 }
356
357 func BenchmarkUnmarshalString(b *testing.B) {
358 b.ReportAllocs()
359 data := []byte(`"hello, world"`)
360 b.RunParallel(func(pb *testing.PB) {
361 var s string
362 for pb.Next() {
363 if err := Unmarshal(data, &s); err != nil {
364 b.Fatalf("Unmarshal error: %v", err)
365 }
366 }
367 })
368 }
369
370 func BenchmarkUnmarshalFloat64(b *testing.B) {
371 b.ReportAllocs()
372 data := []byte(`3.14`)
373 b.RunParallel(func(pb *testing.PB) {
374 var f float64
375 for pb.Next() {
376 if err := Unmarshal(data, &f); err != nil {
377 b.Fatalf("Unmarshal error: %v", err)
378 }
379 }
380 })
381 }
382
383 func BenchmarkUnmarshalInt64(b *testing.B) {
384 b.ReportAllocs()
385 data := []byte(`3`)
386 b.RunParallel(func(pb *testing.PB) {
387 var x int64
388 for pb.Next() {
389 if err := Unmarshal(data, &x); err != nil {
390 b.Fatalf("Unmarshal error: %v", err)
391 }
392 }
393 })
394 }
395
396 func BenchmarkUnmarshalMap(b *testing.B) {
397 b.ReportAllocs()
398 data := []byte(`{"key1":"value1","key2":"value2","key3":"value3"}`)
399 b.RunParallel(func(pb *testing.PB) {
400 x := make(map[string]string, 3)
401 for pb.Next() {
402 if err := Unmarshal(data, &x); err != nil {
403 b.Fatalf("Unmarshal error: %v", err)
404 }
405 }
406 })
407 }
408
409 func BenchmarkIssue10335(b *testing.B) {
410 b.ReportAllocs()
411 j := []byte(`{"a":{ }}`)
412 b.RunParallel(func(pb *testing.PB) {
413 var s struct{}
414 for pb.Next() {
415 if err := Unmarshal(j, &s); err != nil {
416 b.Fatalf("Unmarshal error: %v", err)
417 }
418 }
419 })
420 }
421
422 func BenchmarkIssue34127(b *testing.B) {
423 b.ReportAllocs()
424 j := struct {
425 Bar string `json:"bar,string"`
426 }{
427 Bar: `foobar`,
428 }
429 b.RunParallel(func(pb *testing.PB) {
430 for pb.Next() {
431 if _, err := Marshal(&j); err != nil {
432 b.Fatalf("Marshal error: %v", err)
433 }
434 }
435 })
436 }
437
438 func BenchmarkUnmapped(b *testing.B) {
439 b.ReportAllocs()
440 j := []byte(`{"s": "hello", "y": 2, "o": {"x": 0}, "a": [1, 99, {"x": 1}]}`)
441 b.RunParallel(func(pb *testing.PB) {
442 var s struct{}
443 for pb.Next() {
444 if err := Unmarshal(j, &s); err != nil {
445 b.Fatalf("Unmarshal error: %v", err)
446 }
447 }
448 })
449 }
450
451 func BenchmarkEncodeMarshaler(b *testing.B) {
452 b.ReportAllocs()
453
454 m := struct {
455 A int
456 B RawMessage
457 }{}
458
459 b.RunParallel(func(pb *testing.PB) {
460 enc := NewEncoder(io.Discard)
461
462 for pb.Next() {
463 if err := enc.Encode(&m); err != nil {
464 b.Fatalf("Encode error: %v", err)
465 }
466 }
467 })
468 }
469
470 func BenchmarkEncoderEncode(b *testing.B) {
471 b.ReportAllocs()
472 type T struct {
473 X, Y string
474 }
475 v := &T{"foo", "bar"}
476 b.RunParallel(func(pb *testing.PB) {
477 for pb.Next() {
478 if err := NewEncoder(io.Discard).Encode(v); err != nil {
479 b.Fatalf("Encode error: %v", err)
480 }
481 }
482 })
483 }
484
View as plain text