Skip to content

Commit 7a0895d

Browse files
GODRIVER-3455 Make BSON benchmarks more representative of real use cases. (#1974)
Co-authored-by: Preston Vasquez <[email protected]>
1 parent e922368 commit 7a0895d

File tree

1 file changed

+168
-56
lines changed

1 file changed

+168
-56
lines changed

bson/benchmark_test.go

+168-56
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ import (
1919
"testing"
2020
)
2121

22+
var encodetestBsonD D
23+
24+
func init() {
25+
b, err := Marshal(encodetestInstance)
26+
if err != nil {
27+
panic(fmt.Sprintf("error marshling struct: %v", err))
28+
}
29+
30+
err = Unmarshal(b, &encodetestBsonD)
31+
if err != nil {
32+
panic(fmt.Sprintf("error unmarshaling BSON: %v", err))
33+
}
34+
}
35+
2236
type encodetest struct {
2337
Field1String string
2438
Field1Int64 int64
@@ -184,7 +198,7 @@ func readExtJSONFile(filename string) map[string]interface{} {
184198
func BenchmarkMarshal(b *testing.B) {
185199
cases := []struct {
186200
desc string
187-
value interface{}
201+
value any
188202
}{
189203
{
190204
desc: "simple struct",
@@ -194,6 +208,10 @@ func BenchmarkMarshal(b *testing.B) {
194208
desc: "nested struct",
195209
value: nestedInstance,
196210
},
211+
{
212+
desc: "simple D",
213+
value: encodetestBsonD,
214+
},
197215
{
198216
desc: "deep_bson.json.gz",
199217
value: readExtJSONFile("deep_bson.json.gz"),
@@ -208,119 +226,211 @@ func BenchmarkMarshal(b *testing.B) {
208226
},
209227
}
210228

211-
for _, tc := range cases {
212-
b.Run(tc.desc, func(b *testing.B) {
213-
b.Run("BSON", func(b *testing.B) {
214-
for i := 0; i < b.N; i++ {
215-
_, err := Marshal(tc.value)
216-
if err != nil {
217-
b.Errorf("error marshalling BSON: %s", err)
229+
b.Run("BSON", func(b *testing.B) {
230+
for _, tc := range cases {
231+
tc := tc // Capture range variable.
232+
233+
b.Run(tc.desc, func(b *testing.B) {
234+
b.ReportAllocs()
235+
b.RunParallel(func(pb *testing.PB) {
236+
for pb.Next() {
237+
_, err := Marshal(tc.value)
238+
if err != nil {
239+
b.Errorf("error marshalling BSON: %s", err)
240+
}
218241
}
219-
}
242+
})
220243
})
244+
}
245+
})
221246

222-
b.Run("extJSON", func(b *testing.B) {
223-
for i := 0; i < b.N; i++ {
224-
_, err := MarshalExtJSON(tc.value, true, false)
225-
if err != nil {
226-
b.Errorf("error marshalling extended JSON: %s", err)
247+
b.Run("extJSON", func(b *testing.B) {
248+
for _, tc := range cases {
249+
tc := tc // Capture range variable.
250+
251+
b.Run(tc.desc, func(b *testing.B) {
252+
b.ReportAllocs()
253+
b.RunParallel(func(pb *testing.PB) {
254+
for pb.Next() {
255+
_, err := MarshalExtJSON(tc.value, true, false)
256+
if err != nil {
257+
b.Errorf("error marshalling extended JSON: %s", err)
258+
}
227259
}
228-
}
260+
})
229261
})
262+
}
263+
})
230264

231-
b.Run("JSON", func(b *testing.B) {
232-
for i := 0; i < b.N; i++ {
233-
_, err := json.Marshal(tc.value)
234-
if err != nil {
235-
b.Errorf("error marshalling JSON: %s", err)
265+
b.Run("JSON", func(b *testing.B) {
266+
for _, tc := range cases {
267+
tc := tc // Capture range variable.
268+
269+
b.Run(tc.desc, func(b *testing.B) {
270+
b.ReportAllocs()
271+
b.RunParallel(func(pb *testing.PB) {
272+
for pb.Next() {
273+
_, err := json.Marshal(tc.value)
274+
if err != nil {
275+
b.Errorf("error marshalling JSON: %s", err)
276+
}
236277
}
237-
}
278+
})
238279
})
239-
})
240-
}
280+
}
281+
})
241282
}
242283

243284
func BenchmarkUnmarshal(b *testing.B) {
244-
cases := []struct {
285+
type testcase struct {
245286
desc string
246-
value interface{}
247-
}{
287+
value any
288+
dst func() any
289+
}
290+
291+
cases := []testcase{
248292
{
249293
desc: "simple struct",
250294
value: encodetestInstance,
295+
dst: func() any { return &encodetest{} },
251296
},
252297
{
253298
desc: "nested struct",
254299
value: nestedInstance,
300+
dst: func() any { return &encodetest{} },
255301
},
302+
}
303+
304+
inputs := []struct {
305+
name string
306+
value any
307+
}{
256308
{
257-
desc: "deep_bson.json.gz",
309+
name: "simple",
310+
value: encodetestInstance,
311+
},
312+
{
313+
name: "nested",
314+
value: nestedInstance,
315+
},
316+
{
317+
name: "deep_bson.json.gz",
258318
value: readExtJSONFile("deep_bson.json.gz"),
259319
},
260320
{
261-
desc: "flat_bson.json.gz",
321+
name: "flat_bson.json.gz",
262322
value: readExtJSONFile("flat_bson.json.gz"),
263323
},
264324
{
265-
desc: "full_bson.json.gz",
325+
name: "full_bson.json.gz",
266326
value: readExtJSONFile("full_bson.json.gz"),
267327
},
268328
}
269329

270-
for _, tc := range cases {
271-
b.Run(tc.desc, func(b *testing.B) {
272-
b.Run("BSON", func(b *testing.B) {
330+
destinations := []struct {
331+
name string
332+
dst func() any
333+
}{
334+
{
335+
name: "to map",
336+
dst: func() any { return &map[string]any{} },
337+
},
338+
{
339+
name: "to D",
340+
dst: func() any { return &D{} },
341+
},
342+
}
343+
344+
for _, input := range inputs {
345+
for _, dest := range destinations {
346+
cases = append(cases, testcase{
347+
desc: input.name + " " + dest.name,
348+
value: input.value,
349+
dst: dest.dst,
350+
})
351+
}
352+
}
353+
354+
b.Run("BSON", func(b *testing.B) {
355+
for _, tc := range cases {
356+
tc := tc // Capture range variable.
357+
358+
b.Run(tc.desc, func(b *testing.B) {
359+
b.ReportAllocs()
273360
data, err := Marshal(tc.value)
274361
if err != nil {
275362
b.Errorf("error marshalling BSON: %s", err)
276363
return
277364
}
278365

366+
b.SetBytes(int64(len(data)))
279367
b.ResetTimer()
280-
var v2 map[string]interface{}
281-
for i := 0; i < b.N; i++ {
282-
err := Unmarshal(data, &v2)
283-
if err != nil {
284-
b.Errorf("error unmarshalling BSON: %s", err)
368+
b.RunParallel(func(pb *testing.PB) {
369+
for pb.Next() {
370+
val := tc.dst()
371+
err := Unmarshal(data, val)
372+
if err != nil {
373+
b.Errorf("error unmarshalling BSON: %s", err)
374+
}
285375
}
286-
}
376+
})
287377
})
378+
}
379+
})
380+
381+
b.Run("extJSON", func(b *testing.B) {
382+
for _, tc := range cases {
383+
tc := tc // Capture range variable.
288384

289-
b.Run("extJSON", func(b *testing.B) {
385+
b.Run(tc.desc, func(b *testing.B) {
386+
b.ReportAllocs()
290387
data, err := MarshalExtJSON(tc.value, true, false)
291388
if err != nil {
292389
b.Errorf("error marshalling extended JSON: %s", err)
293390
return
294391
}
295392

393+
b.SetBytes(int64(len(data)))
296394
b.ResetTimer()
297-
var v2 map[string]interface{}
298-
for i := 0; i < b.N; i++ {
299-
err := UnmarshalExtJSON(data, true, &v2)
300-
if err != nil {
301-
b.Errorf("error unmarshalling extended JSON: %s", err)
395+
b.RunParallel(func(pb *testing.PB) {
396+
for pb.Next() {
397+
val := tc.dst()
398+
err := UnmarshalExtJSON(data, true, val)
399+
if err != nil {
400+
b.Errorf("error unmarshalling extended JSON: %s", err)
401+
}
302402
}
303-
}
403+
})
304404
})
405+
}
406+
})
407+
408+
b.Run("JSON", func(b *testing.B) {
409+
for _, tc := range cases {
410+
tc := tc // Capture range variable.
305411

306-
b.Run("JSON", func(b *testing.B) {
412+
b.Run(tc.desc, func(b *testing.B) {
413+
b.ReportAllocs()
307414
data, err := json.Marshal(tc.value)
308415
if err != nil {
309416
b.Errorf("error marshalling JSON: %s", err)
310417
return
311418
}
312419

420+
b.SetBytes(int64(len(data)))
313421
b.ResetTimer()
314-
var v2 map[string]interface{}
315-
for i := 0; i < b.N; i++ {
316-
err := json.Unmarshal(data, &v2)
317-
if err != nil {
318-
b.Errorf("error unmarshalling JSON: %s", err)
422+
b.RunParallel(func(pb *testing.PB) {
423+
for pb.Next() {
424+
val := tc.dst()
425+
err := json.Unmarshal(data, val)
426+
if err != nil {
427+
b.Errorf("error unmarshalling JSON: %s", err)
428+
}
319429
}
320-
}
430+
})
321431
})
322-
})
323-
}
432+
}
433+
})
324434
}
325435

326436
// The following benchmarks are copied from the Go standard library's
@@ -389,13 +499,13 @@ func codeInit() {
389499
}
390500

391501
func BenchmarkCodeUnmarshal(b *testing.B) {
392-
b.ReportAllocs()
393502
if codeJSON == nil {
394503
b.StopTimer()
395504
codeInit()
396505
b.StartTimer()
397506
}
398507
b.Run("BSON", func(b *testing.B) {
508+
b.ReportAllocs()
399509
b.RunParallel(func(pb *testing.PB) {
400510
for pb.Next() {
401511
var r codeResponse
@@ -407,6 +517,7 @@ func BenchmarkCodeUnmarshal(b *testing.B) {
407517
b.SetBytes(int64(len(codeBSON)))
408518
})
409519
b.Run("JSON", func(b *testing.B) {
520+
b.ReportAllocs()
410521
b.RunParallel(func(pb *testing.PB) {
411522
for pb.Next() {
412523
var r codeResponse
@@ -420,13 +531,13 @@ func BenchmarkCodeUnmarshal(b *testing.B) {
420531
}
421532

422533
func BenchmarkCodeMarshal(b *testing.B) {
423-
b.ReportAllocs()
424534
if codeJSON == nil {
425535
b.StopTimer()
426536
codeInit()
427537
b.StartTimer()
428538
}
429539
b.Run("BSON", func(b *testing.B) {
540+
b.ReportAllocs()
430541
b.RunParallel(func(pb *testing.PB) {
431542
for pb.Next() {
432543
if _, err := Marshal(&codeStruct); err != nil {
@@ -437,6 +548,7 @@ func BenchmarkCodeMarshal(b *testing.B) {
437548
b.SetBytes(int64(len(codeBSON)))
438549
})
439550
b.Run("JSON", func(b *testing.B) {
551+
b.ReportAllocs()
440552
b.RunParallel(func(pb *testing.PB) {
441553
for pb.Next() {
442554
if _, err := json.Marshal(&codeStruct); err != nil {

0 commit comments

Comments
 (0)