package jreader import ( "encoding/json" "testing" "github.com/launchdarkly/go-jsonstream/v3/internal/commontest" ) // These benchmarks perform equivalent actions to the ones in reader_benchmark_test.go, but using // the default reflection-based mechanism from the json/encoding package, so we can see how much // less efficient that is than our default implementation and the easyjson implementation. func BenchmarkJSONUnmarshalComparatives(b *testing.B) { b.Run("Null", benchmarkReadNullJSONUnmarshal) b.Run("Boolean", benchmarkReadBooleanJSONUnmarshal) b.Run("NumberInt", benchmarkReadNumberIntJSONUnmarshal) b.Run("NumberFloat", benchmarkReadNumberFloatJSONUnmarshal) b.Run("String", benchmarkReadStringJSONUnmarshal) b.Run("ArrayOfBools", benchmarkReadArrayOfBoolsJSONUnmarshal) b.Run("ArrayOfStrings", benchmarkReadArrayOfStringsJSONUnmarshal) b.Run("Object", benchmarkReadObjectJSONUnmarshal) b.Run("ArrayOfObjects", benchmarkReadArrayOfObjectsJSONUnmarshal) } func benchmarkReadNullJSONUnmarshal(b *testing.B) { data := []byte("null") var expected interface{} = nil b.ResetTimer() for i := 0; i < b.N; i++ { var val interface{} if err := json.Unmarshal(data, &val); err != nil { b.Error(err) b.FailNow() } if val != expected { b.FailNow() } } } func benchmarkReadBooleanJSONUnmarshal(b *testing.B) { data := []byte("true") expected := true b.ResetTimer() for i := 0; i < b.N; i++ { var val bool if err := json.Unmarshal(data, &val); err != nil { b.Error(err) b.FailNow() } if val != expected { b.FailNow() } } } func benchmarkReadNumberIntJSONUnmarshal(b *testing.B) { data := []byte("1234") expected := 1234 b.ResetTimer() for i := 0; i < b.N; i++ { var val int if err := json.Unmarshal(data, &val); err != nil { b.Error(err) b.FailNow() } if val != expected { b.FailNow() } } } func benchmarkReadNumberFloatJSONUnmarshal(b *testing.B) { data := []byte("1234.5") expected := 1234.5 b.ResetTimer() for i := 0; i < b.N; i++ { var val float64 if err := json.Unmarshal(data, &val); err != nil { b.Error(err) b.FailNow() } if val != expected { b.FailNow() } } } func benchmarkReadStringJSONUnmarshal(b *testing.B) { data := []byte(`"abc"`) expected := "abc" b.ResetTimer() for i := 0; i < b.N; i++ { var val string if err := json.Unmarshal(data, &val); err != nil { b.Error(err) b.FailNow() } if val != expected { b.FailNow() } } } func benchmarkReadArrayOfBoolsJSONUnmarshal(b *testing.B) { expected := commontest.MakeBools() data := commontest.MakeBoolsJSON(expected) b.ResetTimer() for i := 0; i < b.N; i++ { var vals []bool if err := json.Unmarshal(data, &vals); err != nil { b.Error(err) b.FailNow() } if len(vals) < len(expected) { b.FailNow() } } } func benchmarkReadArrayOfStringsJSONUnmarshal(b *testing.B) { expected := commontest.MakeStrings() data := commontest.MakeStringsJSON(expected) b.ResetTimer() for i := 0; i < b.N; i++ { var vals []string if err := json.Unmarshal(data, &vals); err != nil { b.Error(err) b.FailNow() } if len(vals) < len(expected) { b.FailNow() } } } func benchmarkReadObjectJSONUnmarshal(b *testing.B) { for i := 0; i < b.N; i++ { var val ExampleStructWrapper if err := json.Unmarshal(commontest.ExampleStructData, &val); err != nil { b.Error(err) b.FailNow() } if val != ExampleStructWrapper(commontest.ExampleStructValue) { b.FailNow() } } } func benchmarkReadArrayOfObjectsJSONUnmarshal(b *testing.B) { rawStructs := commontest.MakeStructs() data := commontest.MakeStructsJSON(rawStructs) var expected []ExampleStructWrapper for _, rawStruct := range rawStructs { expected = append(expected, ExampleStructWrapper(rawStruct)) } b.ResetTimer() for i := 0; i < b.N; i++ { var values []ExampleStructWrapper if err := json.Unmarshal(data, &values); err != nil { b.Error(err) b.FailNow() } for i, val := range values { if val != expected[i] { b.FailNow() } } } }