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