easyjson
easyjson copied to clipboard
Question: Why using easyjson structs for Marshal with encoding/json is so inefficient?
Hey - I've tried to benchmark your library in terms of its cooperation with encoding/json
tl;dr; Using easy json generated struct for Marshal (with encoding/json) is much worse than using the same struct without easy json generated code.
BenchmarkMarshalEasyJsonWithEncoding-8 124141 9555 ns/op 3126 B/op 8 allocs/op
BenchmarkUnmarshalEasyJsonWithEncoding-8 103888 11387 ns/op 976 B/op 31 allocs/op
BenchmarkMarshalNormalJsonWithEncoding-8 397566 2988 ns/op 1472 B/op 2 allocs/op
BenchmarkUnmarshalNormalJsonWithEncoding-8 102706 12116 ns/op 992 B/op 32 allocs/op
So my thought was that most of libraries are using encoding/json underneath - so if I can generate efficient MarshalJSON and UnmarshalJSON implementations for my structs I can get boost up in the performance
Sadly in mine test the results were different and I would like to know why
Structs used in test:
//easyjson:json
type EasyJsonStruct struct {
Field1 string `json:"field1,omitempty"`
Field2 string `json:"field2,omitempty"`
Field3 []string `json:"field3,omitempty"`
Field4 string `json:"field4,omitempty"`
Field5 string `json:"field5,omitempty"`
Field6 string `json:"field6,omitempty"`
Field7 *int8 `json:"field7,omitempty"`
Field8 *bool `json:"field8,omitempty"`
Field9 *bool `json:"field9,omitempty"`
Field10 string `json:"field10,omitempty"`
Field11 string `json:"field11,omitempty"`
Field12 string `json:"field12,omitempty"`
Field13 string `json:"field13,omitempty"`
Field14 string `json:"field14,omitempty"`
Field15 []string `json:"field15,omitempty"`
Field16 *bool `json:"field16,omitempty"`
Field17 string `json:"field17,omitempty"`
Field18 string `json:"field18,omitempty"`
Field19 string `json:"field19,omitempty"`
Field20 string `json:"field20,omitempty"`
Field21 string `json:"field21,omitempty"`
Field22 string `json:"field22,omitempty"`
Field23 string `json:"field23,omitempty"`
Field24 []string `json:"field24,omitempty"`
Field25 []string `json:"field25,omitempty"`
Field26 []string `json:"field26,omitempty"`
Field27 string `json:"field27,omitempty"`
}
//easyjson:skip
type JsonStruct struct {
Field1 string `json:"field1,omitempty"`
Field2 string `json:"field2,omitempty"`
Field3 []string `json:"field3,omitempty"`
Field4 string `json:"field4,omitempty"`
Field5 string `json:"field5,omitempty"`
Field6 string `json:"field6,omitempty"`
Field7 *int8 `json:"field7,omitempty"`
Field8 *bool `json:"field8,omitempty"`
Field9 *bool `json:"field9,omitempty"`
Field10 string `json:"field10,omitempty"`
Field11 string `json:"field11,omitempty"`
Field12 string `json:"field12,omitempty"`
Field13 string `json:"field13,omitempty"`
Field14 string `json:"field14,omitempty"`
Field15 []string `json:"field15,omitempty"`
Field16 *bool `json:"field16,omitempty"`
Field17 string `json:"field17,omitempty"`
Field18 string `json:"field18,omitempty"`
Field19 string `json:"field19,omitempty"`
Field20 string `json:"field20,omitempty"`
Field21 string `json:"field21,omitempty"`
Field22 string `json:"field22,omitempty"`
Field23 string `json:"field23,omitempty"`
Field24 []string `json:"field24,omitempty"`
Field25 []string `json:"field25,omitempty"`
Field26 []string `json:"field26,omitempty"`
Field27 string `json:"field27,omitempty"`
}
The test:
package main
import (
"encoding/json"
"testing"
)
var jsonStruct JsonStruct
var jsonStructBytes []byte
var easyJsonStruct EasyJsonStruct
var easyJsonStructBytes []byte
func init() {
testBool := true
testInt8 := int8(1)
jsonStruct = JsonStruct{
Field1: "testData121453vvczcsdwdgw",
Field2: "testData121453vvczcsdwdgw",
Field3: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field4: "testData121453vvczcsdwdgw",
Field5: "testData121453vvczcsdwdgw",
Field6: "testData121453vvczcsdwdgw",
Field7: &testInt8,
Field8: &testBool,
Field9: &testBool,
Field10: "testData121453vvczcsdwdgw",
Field11: "testData121453vvczcsdwdgw",
Field12: "testData121453vvczcsdwdgw",
Field13: "testData121453vvczcsdwdgw",
Field14: "testData121453vvczcsdwdgw",
Field15: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field16: &testBool,
Field17: "testData121453vvczcsdwdgw",
Field18: "testData121453vvczcsdwdgw",
Field19: "testData121453vvczcsdwdgw",
Field20: "testData121453vvczcsdwdgw",
Field21: "testData121453vvczcsdwdgw",
Field22: "testData121453vvczcsdwdgw",
Field23: "testData121453vvczcsdwdgw",
Field24: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field25: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field26: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field27: "testData121453vvczcsdwdgw",
}
easyJsonStruct = EasyJsonStruct{
Field1: "testData121453vvczcsdwdgw",
Field2: "testData121453vvczcsdwdgw",
Field3: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field4: "testData121453vvczcsdwdgw",
Field5: "testData121453vvczcsdwdgw",
Field6: "testData121453vvczcsdwdgw",
Field7: &testInt8,
Field8: &testBool,
Field9: &testBool,
Field10: "testData121453vvczcsdwdgw",
Field11: "testData121453vvczcsdwdgw",
Field12: "testData121453vvczcsdwdgw",
Field13: "testData121453vvczcsdwdgw",
Field14: "testData121453vvczcsdwdgw",
Field15: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field16: &testBool,
Field17: "testData121453vvczcsdwdgw",
Field18: "testData121453vvczcsdwdgw",
Field19: "testData121453vvczcsdwdgw",
Field20: "testData121453vvczcsdwdgw",
Field21: "testData121453vvczcsdwdgw",
Field22: "testData121453vvczcsdwdgw",
Field23: "testData121453vvczcsdwdgw",
Field24: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field25: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field26: []string{"testData121453vvczcsdwdgw", "fsadfdsf"},
Field27: "testData121453vvczcsdwdgw",
}
easyJsonStructBytes, _ = json.Marshal(easyJsonStruct)
jsonStructBytes, _ = json.Marshal(jsonStruct)
}
func BenchmarkMarshalEasyJsonWithEncoding(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
_, _ = json.Marshal(easyJsonStruct)
}
}
func BenchmarkUnmarshalEasyJsonWithEncoding(b *testing.B) {
var obj EasyJsonStruct
b.ReportAllocs()
for n := 0; n < b.N; n++ {
_ = json.Unmarshal(easyJsonStructBytes, &obj)
}
}
func BenchmarkMarshalNormalJsonWithEncoding(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
_, _ = json.Marshal(jsonStruct)
}
}
func BenchmarkUnmarshalNormalJsonWithEncoding(b *testing.B) {
var obj JsonStruct
b.ReportAllocs()
for n := 0; n < b.N; n++ {
_ = json.Unmarshal(jsonStructBytes, &obj)
}
}
easyJson must be generate xxx_easyjson.go, and call generate file.