Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Why using easyjson structs for Marshal with encoding/json is so inefficient? #343

Open
crisperit opened this issue Aug 4, 2021 · 1 comment

Comments

@crisperit
Copy link

crisperit commented Aug 4, 2021

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)
	}
}
@lpflpf
Copy link

lpflpf commented Aug 9, 2021

easyJson must be generate xxx_easyjson.go, and call generate file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants