Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 168 additions & 56 deletions bson/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ import (
"testing"
)

var encodetestBsonD D

func init() {
b, err := Marshal(encodetestInstance)
if err != nil {
panic(fmt.Sprintf("error marshling struct: %v", err))
}

err = Unmarshal(b, &encodetestBsonD)
if err != nil {
panic(fmt.Sprintf("error unmarshaling BSON: %v", err))
}
}

type encodetest struct {
Field1String string
Field1Int64 int64
Expand Down Expand Up @@ -184,7 +198,7 @@ func readExtJSONFile(filename string) map[string]interface{} {
func BenchmarkMarshal(b *testing.B) {
cases := []struct {
desc string
value interface{}
value any
}{
{
desc: "simple struct",
Expand All @@ -194,6 +208,10 @@ func BenchmarkMarshal(b *testing.B) {
desc: "nested struct",
value: nestedInstance,
},
{
desc: "simple D",
value: encodetestBsonD,
},
{
desc: "deep_bson.json.gz",
value: readExtJSONFile("deep_bson.json.gz"),
Expand All @@ -208,119 +226,211 @@ func BenchmarkMarshal(b *testing.B) {
},
}

for _, tc := range cases {
b.Run(tc.desc, func(b *testing.B) {
b.Run("BSON", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := Marshal(tc.value)
if err != nil {
b.Errorf("error marshalling BSON: %s", err)
b.Run("BSON", func(b *testing.B) {
for _, tc := range cases {
tc := tc // Capture range variable.

b.Run(tc.desc, func(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := Marshal(tc.value)
if err != nil {
b.Errorf("error marshalling BSON: %s", err)
}
}
}
})
})
}
})

b.Run("extJSON", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := MarshalExtJSON(tc.value, true, false)
if err != nil {
b.Errorf("error marshalling extended JSON: %s", err)
b.Run("extJSON", func(b *testing.B) {
for _, tc := range cases {
tc := tc // Capture range variable.

b.Run(tc.desc, func(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := MarshalExtJSON(tc.value, true, false)
if err != nil {
b.Errorf("error marshalling extended JSON: %s", err)
}
}
}
})
})
}
})

b.Run("JSON", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := json.Marshal(tc.value)
if err != nil {
b.Errorf("error marshalling JSON: %s", err)
b.Run("JSON", func(b *testing.B) {
for _, tc := range cases {
tc := tc // Capture range variable.

b.Run(tc.desc, func(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := json.Marshal(tc.value)
if err != nil {
b.Errorf("error marshalling JSON: %s", err)
}
}
}
})
})
})
}
}
})
}

func BenchmarkUnmarshal(b *testing.B) {
cases := []struct {
type testcase struct {
desc string
value interface{}
}{
value any
dst func() any
}

cases := []testcase{
{
desc: "simple struct",
value: encodetestInstance,
dst: func() any { return &encodetest{} },
},
{
desc: "nested struct",
value: nestedInstance,
dst: func() any { return &encodetest{} },
},
}

inputs := []struct {
name string
value any
}{
{
desc: "deep_bson.json.gz",
name: "simple",
value: encodetestInstance,
},
{
name: "nested",
value: nestedInstance,
},
{
name: "deep_bson.json.gz",
value: readExtJSONFile("deep_bson.json.gz"),
},
{
desc: "flat_bson.json.gz",
name: "flat_bson.json.gz",
value: readExtJSONFile("flat_bson.json.gz"),
},
{
desc: "full_bson.json.gz",
name: "full_bson.json.gz",
value: readExtJSONFile("full_bson.json.gz"),
},
}

for _, tc := range cases {
b.Run(tc.desc, func(b *testing.B) {
b.Run("BSON", func(b *testing.B) {
destinations := []struct {
name string
dst func() any
}{
{
name: "to map",
dst: func() any { return &map[string]any{} },
},
{
name: "to D",
dst: func() any { return &D{} },
},
}

for _, input := range inputs {
for _, dest := range destinations {
cases = append(cases, testcase{
desc: input.name + " " + dest.name,
value: input.value,
dst: dest.dst,
})
}
}

b.Run("BSON", func(b *testing.B) {
for _, tc := range cases {
tc := tc // Capture range variable.

b.Run(tc.desc, func(b *testing.B) {
b.ReportAllocs()
data, err := Marshal(tc.value)
if err != nil {
b.Errorf("error marshalling BSON: %s", err)
return
}

b.SetBytes(int64(len(data)))
b.ResetTimer()
var v2 map[string]interface{}
for i := 0; i < b.N; i++ {
err := Unmarshal(data, &v2)
if err != nil {
b.Errorf("error unmarshalling BSON: %s", err)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
val := tc.dst()
err := Unmarshal(data, val)
if err != nil {
b.Errorf("error unmarshalling BSON: %s", err)
}
}
}
})
})
}
})

b.Run("extJSON", func(b *testing.B) {
for _, tc := range cases {
tc := tc // Capture range variable.

b.Run("extJSON", func(b *testing.B) {
b.Run(tc.desc, func(b *testing.B) {
b.ReportAllocs()
data, err := MarshalExtJSON(tc.value, true, false)
if err != nil {
b.Errorf("error marshalling extended JSON: %s", err)
return
}

b.SetBytes(int64(len(data)))
b.ResetTimer()
var v2 map[string]interface{}
for i := 0; i < b.N; i++ {
err := UnmarshalExtJSON(data, true, &v2)
if err != nil {
b.Errorf("error unmarshalling extended JSON: %s", err)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
val := tc.dst()
err := UnmarshalExtJSON(data, true, val)
if err != nil {
b.Errorf("error unmarshalling extended JSON: %s", err)
}
}
}
})
})
}
})

b.Run("JSON", func(b *testing.B) {
for _, tc := range cases {
tc := tc // Capture range variable.

b.Run("JSON", func(b *testing.B) {
b.Run(tc.desc, func(b *testing.B) {
b.ReportAllocs()
data, err := json.Marshal(tc.value)
if err != nil {
b.Errorf("error marshalling JSON: %s", err)
return
}

b.SetBytes(int64(len(data)))
b.ResetTimer()
var v2 map[string]interface{}
for i := 0; i < b.N; i++ {
err := json.Unmarshal(data, &v2)
if err != nil {
b.Errorf("error unmarshalling JSON: %s", err)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
val := tc.dst()
err := json.Unmarshal(data, val)
if err != nil {
b.Errorf("error unmarshalling JSON: %s", err)
}
}
}
})
})
})
}
}
})
}

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

func BenchmarkCodeUnmarshal(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.Run("BSON", func(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var r codeResponse
Expand All @@ -407,6 +517,7 @@ func BenchmarkCodeUnmarshal(b *testing.B) {
b.SetBytes(int64(len(codeBSON)))
})
b.Run("JSON", func(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var r codeResponse
Expand All @@ -420,13 +531,13 @@ func BenchmarkCodeUnmarshal(b *testing.B) {
}

func BenchmarkCodeMarshal(b *testing.B) {
b.ReportAllocs()
if codeJSON == nil {
b.StopTimer()
codeInit()
b.StartTimer()
}
b.Run("BSON", func(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := Marshal(&codeStruct); err != nil {
Expand All @@ -437,6 +548,7 @@ func BenchmarkCodeMarshal(b *testing.B) {
b.SetBytes(int64(len(codeBSON)))
})
b.Run("JSON", func(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
if _, err := json.Marshal(&codeStruct); err != nil {
Expand Down
Loading