gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

commit b4dd8c5c12a5e401713da86d27bc8355d352595a
parent 778eb357aad7d75b88a2da6d91dd3b62d7ffee6b
Author: Francois Parquet <francois.parquet@gmail.com>
Date:   Thu, 26 Apr 2018 20:07:55 +0800

Merge pull request #2 from francoispqt/update/add-benchmarks adding EasyJson benchmarks

Update/add benchmarks
Diffstat:
MREADME.md | 9++++++++-
Mbenchmarks/benchmarks_large.go | 1+
Abenchmarks/benchmarks_large_easyjson.go | 426+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbenchmarks/benchmarks_medium.go | 1+
Abenchmarks/benchmarks_medium_easyjson.go | 560+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbenchmarks/benchmarks_small.go | 1+
Abenchmarks/benchmarks_small_easyjson.go | 186+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbenchmarks/decoder/decoder_bench_large_test.go | 9+++++++++
Mbenchmarks/decoder/decoder_bench_medium_test.go | 14++++++++------
Mbenchmarks/decoder/decoder_bench_small_test.go | 9+++++++++
Mbenchmarks/encoder/encoder_bench_large_test.go | 10++++++++++
Mbenchmarks/encoder/encoder_bench_medium_test.go | 10++++++++++
Mbenchmarks/encoder/encoder_bench_small_test.go | 10++++++++++
13 files changed, 1239 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md @@ -315,6 +315,7 @@ cd $GOPATH/src/github.com/francoispqt/gojay/benchmarks/encoder && make bench | Std Library | 4661 | 496 | 12 | | JsonParser | 1313 | 0 | 0 | | JsonIter | 899 | 192 | 5 | +| EasyJson | 929 | 240 | 2 | | GoJay | 662 | 112 | 1 | ### Medium Payload @@ -326,8 +327,9 @@ cd $GOPATH/src/github.com/francoispqt/gojay/benchmarks/encoder && make bench |-------------|-------|--------------|-----------| | Std Library | 30148 | 2152 | 496 | | JsonParser | 7793 | 0 | 0 | +| EasyJson | 7957 | 232 | 6 | | JsonIter | 5967 | 496 | 44 | -| GoJay | 3914 | 128 | 12 | +| GoJay | 3914 | 128 | 7 | ### Large Payload [benchmark code is here](https://github.com/francoispqt/gojay/blob/master/benchmarks/decoder/decoder_bench_large_test.go) @@ -336,6 +338,7 @@ cd $GOPATH/src/github.com/francoispqt/gojay/benchmarks/encoder && make bench | | ns/op | bytes/op | allocs/op | |-------------|-------|--------------|-----------| +| EasyJson | 106626| 160 | 2 | | JsonParser | 66813 | 0 | 0 | | JsonIter | 87994 | 6738 | 329 | | GoJay | 43402 | 1408 | 76 | @@ -352,8 +355,10 @@ cd $GOPATH/src/github.com/francoispqt/gojay/benchmarks/encoder && make bench | | ns/op | bytes/op | allocs/op | |-------------|-------|--------------|-----------| | Std Library | 1280 | 464 | 3 | +| EasyJson | 871 | 944 | 6 | | JsonIter | 866 | 272 | 3 | | GoJay | 484 | 320 | 2 | + ### Medium Struct [benchmark code is here](https://github.com/francoispqt/gojay/blob/master/benchmarks/encoder/encoder_bench_medium_test.go) @@ -362,6 +367,7 @@ cd $GOPATH/src/github.com/francoispqt/gojay/benchmarks/encoder && make bench | | ns/op | bytes/op | allocs/op | |-------------|-------|--------------|-----------| | Std Library | 3325 | 1496 | 18 | +| EasyJson | 1997 | 1320 | 19 | | JsonIter | 1939 | 648 | 16 | | GoJay | 1196 | 936 | 16 | @@ -374,6 +380,7 @@ cd $GOPATH/src/github.com/francoispqt/gojay/benchmarks/encoder && make bench |-------------|-------|--------------|-----------| | Std Library | 51317 | 28704 | 326 | | JsonIter | 35247 | 14608 | 320 | +| EasyJson | 32053 | 15474 | 327 | | GoJay | 27847 | 27888 | 326 | # Contributing diff --git a/benchmarks/benchmarks_large.go b/benchmarks/benchmarks_large.go @@ -128,6 +128,7 @@ func (m *LargePayload) NKeys() int { return 2 } +//easyjson:json func (m *LargePayload) MarshalObject(enc *gojay.Encoder) { enc.AddArrayKey("users", &m.Users) enc.AddObjectKey("topics", m.Topics) diff --git a/benchmarks/benchmarks_large_easyjson.go b/benchmarks/benchmarks_large_easyjson.go @@ -0,0 +1,426 @@ +// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. + +package benchmarks + +import ( + json "encoding/json" + + easyjson "github.com/mailru/easyjson" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" +) + +// suppress unused package warning +var ( + _ *json.RawMessage + _ *jlexer.Lexer + _ *jwriter.Writer + _ easyjson.Marshaler +) + +func easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks(in *jlexer.Lexer, out *LargePayload) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Users": + if in.IsNull() { + in.Skip() + out.Users = nil + } else { + in.Delim('[') + if out.Users == nil { + if !in.IsDelim(']') { + out.Users = make(DSUsers, 0, 8) + } else { + out.Users = DSUsers{} + } + } else { + out.Users = (out.Users)[:0] + } + for !in.IsDelim(']') { + var v1 *DSUser + if in.IsNull() { + in.Skip() + v1 = nil + } else { + if v1 == nil { + v1 = new(DSUser) + } + (*v1).UnmarshalEasyJSON(in) + } + out.Users = append(out.Users, v1) + in.WantComma() + } + in.Delim(']') + } + case "Topics": + if in.IsNull() { + in.Skip() + out.Topics = nil + } else { + if out.Topics == nil { + out.Topics = new(DSTopicsList) + } + (*out.Topics).UnmarshalEasyJSON(in) + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks(out *jwriter.Writer, in LargePayload) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"Users\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Users == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v2, v3 := range in.Users { + if v2 > 0 { + out.RawByte(',') + } + if v3 == nil { + out.RawString("null") + } else { + (*v3).MarshalEasyJSON(out) + } + } + out.RawByte(']') + } + } + { + const prefix string = ",\"Topics\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Topics == nil { + out.RawString("null") + } else { + (*in.Topics).MarshalEasyJSON(out) + } + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v LargePayload) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v LargePayload) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *LargePayload) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *LargePayload) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks(l, v) +} +func easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks1(in *jlexer.Lexer, out *DSUser) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Username": + out.Username = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks1(out *jwriter.Writer, in DSUser) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"Username\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Username)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v DSUser) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks1(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v DSUser) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks1(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *DSUser) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks1(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *DSUser) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks1(l, v) +} +func easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks2(in *jlexer.Lexer, out *DSTopicsList) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Topics": + if in.IsNull() { + in.Skip() + out.Topics = nil + } else { + in.Delim('[') + if out.Topics == nil { + if !in.IsDelim(']') { + out.Topics = make(DSTopics, 0, 8) + } else { + out.Topics = DSTopics{} + } + } else { + out.Topics = (out.Topics)[:0] + } + for !in.IsDelim(']') { + var v4 *DSTopic + if in.IsNull() { + in.Skip() + v4 = nil + } else { + if v4 == nil { + v4 = new(DSTopic) + } + (*v4).UnmarshalEasyJSON(in) + } + out.Topics = append(out.Topics, v4) + in.WantComma() + } + in.Delim(']') + } + case "MoreTopicsUrl": + out.MoreTopicsUrl = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks2(out *jwriter.Writer, in DSTopicsList) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"Topics\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Topics == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v5, v6 := range in.Topics { + if v5 > 0 { + out.RawByte(',') + } + if v6 == nil { + out.RawString("null") + } else { + (*v6).MarshalEasyJSON(out) + } + } + out.RawByte(']') + } + } + { + const prefix string = ",\"MoreTopicsUrl\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.MoreTopicsUrl)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v DSTopicsList) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks2(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v DSTopicsList) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks2(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *DSTopicsList) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks2(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *DSTopicsList) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks2(l, v) +} +func easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks3(in *jlexer.Lexer, out *DSTopic) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Id": + out.Id = int(in.Int()) + case "Slug": + out.Slug = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks3(out *jwriter.Writer, in DSTopic) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"Id\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.Int(int(in.Id)) + } + { + const prefix string = ",\"Slug\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Slug)) + } + out.RawByte('}') +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v DSTopic) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonCfe4e5f0EncodeGithubComFrancoispqtGojayBenchmarks3(w, v) +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *DSTopic) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonCfe4e5f0DecodeGithubComFrancoispqtGojayBenchmarks3(l, v) +} diff --git a/benchmarks/benchmarks_medium.go b/benchmarks/benchmarks_medium.go @@ -240,6 +240,7 @@ func (m *CBPerson) IsNil() bool { return m == nil } +//easyjson:json type MediumPayload struct { Person *CBPerson `json:"person"` Company string `json:"company"` diff --git a/benchmarks/benchmarks_medium_easyjson.go b/benchmarks/benchmarks_medium_easyjson.go @@ -0,0 +1,560 @@ +// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. + +package benchmarks + +import ( + json "encoding/json" + + easyjson "github.com/mailru/easyjson" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" +) + +// suppress unused package warning +var ( + _ *json.RawMessage + _ *jlexer.Lexer + _ *jwriter.Writer + _ easyjson.Marshaler +) + +func easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks(in *jlexer.Lexer, out *MediumPayload) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "person": + if in.IsNull() { + in.Skip() + out.Person = nil + } else { + if out.Person == nil { + out.Person = new(CBPerson) + } + (*out.Person).UnmarshalEasyJSON(in) + } + case "company": + out.Company = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks(out *jwriter.Writer, in MediumPayload) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"person\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Person == nil { + out.RawString("null") + } else { + (*in.Person).MarshalEasyJSON(out) + } + } + { + const prefix string = ",\"company\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Company)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v MediumPayload) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v MediumPayload) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *MediumPayload) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *MediumPayload) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks(l, v) +} +func easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks1(in *jlexer.Lexer, out *CBPerson) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "name": + if in.IsNull() { + in.Skip() + out.Name = nil + } else { + if out.Name == nil { + out.Name = new(CBName) + } + (*out.Name).UnmarshalEasyJSON(in) + } + case "github": + if in.IsNull() { + in.Skip() + out.Github = nil + } else { + if out.Github == nil { + out.Github = new(CBGithub) + } + (*out.Github).UnmarshalEasyJSON(in) + } + case "Gravatar": + if in.IsNull() { + in.Skip() + out.Gravatar = nil + } else { + if out.Gravatar == nil { + out.Gravatar = new(CBGravatar) + } + (*out.Gravatar).UnmarshalEasyJSON(in) + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks1(out *jwriter.Writer, in CBPerson) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"name\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Name == nil { + out.RawString("null") + } else { + (*in.Name).MarshalEasyJSON(out) + } + } + { + const prefix string = ",\"github\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Github == nil { + out.RawString("null") + } else { + (*in.Github).MarshalEasyJSON(out) + } + } + { + const prefix string = ",\"Gravatar\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Gravatar == nil { + out.RawString("null") + } else { + (*in.Gravatar).MarshalEasyJSON(out) + } + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v CBPerson) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks1(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v CBPerson) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks1(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *CBPerson) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks1(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *CBPerson) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks1(l, v) +} +func easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks2(in *jlexer.Lexer, out *CBName) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "fullName": + out.FullName = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks2(out *jwriter.Writer, in CBName) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"fullName\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.FullName)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v CBName) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks2(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v CBName) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks2(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *CBName) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks2(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *CBName) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks2(l, v) +} +func easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks3(in *jlexer.Lexer, out *CBGravatar) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Avatars": + if in.IsNull() { + in.Skip() + out.Avatars = nil + } else { + in.Delim('[') + if out.Avatars == nil { + if !in.IsDelim(']') { + out.Avatars = make(Avatars, 0, 8) + } else { + out.Avatars = Avatars{} + } + } else { + out.Avatars = (out.Avatars)[:0] + } + for !in.IsDelim(']') { + var v1 *CBAvatar + if in.IsNull() { + in.Skip() + v1 = nil + } else { + if v1 == nil { + v1 = new(CBAvatar) + } + (*v1).UnmarshalEasyJSON(in) + } + out.Avatars = append(out.Avatars, v1) + in.WantComma() + } + in.Delim(']') + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks3(out *jwriter.Writer, in CBGravatar) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"Avatars\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + if in.Avatars == nil && (out.Flags&jwriter.NilSliceAsEmpty) == 0 { + out.RawString("null") + } else { + out.RawByte('[') + for v2, v3 := range in.Avatars { + if v2 > 0 { + out.RawByte(',') + } + if v3 == nil { + out.RawString("null") + } else { + (*v3).MarshalEasyJSON(out) + } + } + out.RawByte(']') + } + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v CBGravatar) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks3(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v CBGravatar) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks3(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *CBGravatar) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks3(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *CBGravatar) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks3(l, v) +} +func easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks4(in *jlexer.Lexer, out *CBGithub) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Followers": + out.Followers = int(in.Int()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks4(out *jwriter.Writer, in CBGithub) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"Followers\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.Int(int(in.Followers)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v CBGithub) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks4(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v CBGithub) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks4(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *CBGithub) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks4(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *CBGithub) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks4(l, v) +} +func easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks5(in *jlexer.Lexer, out *CBAvatar) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Url": + out.Url = string(in.String()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks5(out *jwriter.Writer, in CBAvatar) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"Url\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Url)) + } + out.RawByte('}') +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v CBAvatar) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonB0500db0EncodeGithubComFrancoispqtGojayBenchmarks5(w, v) +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *CBAvatar) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonB0500db0DecodeGithubComFrancoispqtGojayBenchmarks5(l, v) +} diff --git a/benchmarks/benchmarks_small.go b/benchmarks/benchmarks_small.go @@ -4,6 +4,7 @@ import "github.com/francoispqt/gojay" var SmallFixture = []byte(`{"st": 1,"sid": 486,"tt": "active","gr": 0,"uuid": "de305d54-75b4-431b-adb2-eb6b9e546014","ip": "127.0.0.1","ua": "user_agent","tz": -6,"v": 1}`) +//easyjson:json type SmallPayload struct { St int Sid int diff --git a/benchmarks/benchmarks_small_easyjson.go b/benchmarks/benchmarks_small_easyjson.go @@ -0,0 +1,186 @@ +// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT. + +package benchmarks + +import ( + json "encoding/json" + easyjson "github.com/mailru/easyjson" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" +) + +// suppress unused package warning +var ( + _ *json.RawMessage + _ *jlexer.Lexer + _ *jwriter.Writer + _ easyjson.Marshaler +) + +func easyjson890029d8DecodeGithubComFrancoispqtGojayBenchmarks(in *jlexer.Lexer, out *SmallPayload) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "St": + out.St = int(in.Int()) + case "Sid": + out.Sid = int(in.Int()) + case "Tt": + out.Tt = string(in.String()) + case "Gr": + out.Gr = int(in.Int()) + case "Uuid": + out.Uuid = string(in.String()) + case "Ip": + out.Ip = string(in.String()) + case "Ua": + out.Ua = string(in.String()) + case "Tz": + out.Tz = int(in.Int()) + case "V": + out.V = int(in.Int()) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjson890029d8EncodeGithubComFrancoispqtGojayBenchmarks(out *jwriter.Writer, in SmallPayload) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"St\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.Int(int(in.St)) + } + { + const prefix string = ",\"Sid\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.Int(int(in.Sid)) + } + { + const prefix string = ",\"Tt\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Tt)) + } + { + const prefix string = ",\"Gr\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.Int(int(in.Gr)) + } + { + const prefix string = ",\"Uuid\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Uuid)) + } + { + const prefix string = ",\"Ip\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Ip)) + } + { + const prefix string = ",\"Ua\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.String(string(in.Ua)) + } + { + const prefix string = ",\"Tz\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.Int(int(in.Tz)) + } + { + const prefix string = ",\"V\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + out.Int(int(in.V)) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v SmallPayload) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjson890029d8EncodeGithubComFrancoispqtGojayBenchmarks(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v SmallPayload) MarshalEasyJSON(w *jwriter.Writer) { + easyjson890029d8EncodeGithubComFrancoispqtGojayBenchmarks(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *SmallPayload) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjson890029d8DecodeGithubComFrancoispqtGojayBenchmarks(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *SmallPayload) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjson890029d8DecodeGithubComFrancoispqtGojayBenchmarks(l, v) +} diff --git a/benchmarks/decoder/decoder_bench_large_test.go b/benchmarks/decoder/decoder_bench_large_test.go @@ -7,6 +7,7 @@ import ( "github.com/francoispqt/gojay" "github.com/francoispqt/gojay/benchmarks" jsoniter "github.com/json-iterator/go" + "github.com/mailru/easyjson" ) func BenchmarkJsonParserDecodeObjLarge(b *testing.B) { @@ -33,6 +34,14 @@ func BenchmarkJsonIterDecodeObjLarge(b *testing.B) { } } +func BenchmarkEasyJsonDecodeObjLarge(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + result := benchmarks.LargePayload{} + easyjson.Unmarshal(benchmarks.LargeFixture, &result) + } +} + func BenchmarkGoJayDecodeObjLarge(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { diff --git a/benchmarks/decoder/decoder_bench_medium_test.go b/benchmarks/decoder/decoder_bench_medium_test.go @@ -8,6 +8,7 @@ import ( "github.com/francoispqt/gojay" "github.com/francoispqt/gojay/benchmarks" jsoniter "github.com/json-iterator/go" + "github.com/mailru/easyjson" ) func BenchmarkJsonIterDecodeObjMedium(b *testing.B) { @@ -39,15 +40,16 @@ func BenchmarkEncodingJsonStructMedium(b *testing.B) { for i := 0; i < b.N; i++ { var data = benchmarks.MediumPayload{} json.Unmarshal(benchmarks.MediumFixture, &data) - - nothing(data.Person.Name.FullName, data.Person.Github.Followers, data.Company) - - for _, el := range data.Person.Gravatar.Avatars { - nothing(el.Url) - } } } +func BenchmarkEasyJsonDecodeObjMedium(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + result := benchmarks.MediumPayload{} + easyjson.Unmarshal(benchmarks.MediumFixture, &result) + } +} func BenchmarkGoJayDecodeObjMedium(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { diff --git a/benchmarks/decoder/decoder_bench_small_test.go b/benchmarks/decoder/decoder_bench_small_test.go @@ -9,6 +9,7 @@ import ( "github.com/francoispqt/gojay" "github.com/francoispqt/gojay/benchmarks" jsoniter "github.com/json-iterator/go" + "github.com/mailru/easyjson" ) func BenchmarkJSONDecodeObjSmall(b *testing.B) { @@ -43,6 +44,14 @@ func BenchmarkJsonIterDecodeObjSmall(b *testing.B) { } } +func BenchmarkEasyJsonDecodeObjSmall(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + result := benchmarks.SmallPayload{} + easyjson.Unmarshal(benchmarks.SmallFixture, &result) + } +} + func BenchmarkGoJayDecodeObjSmall(b *testing.B) { b.ReportAllocs() for n := 0; n < b.N; n++ { diff --git a/benchmarks/encoder/encoder_bench_large_test.go b/benchmarks/encoder/encoder_bench_large_test.go @@ -8,6 +8,7 @@ import ( "github.com/francoispqt/gojay" "github.com/francoispqt/gojay/benchmarks" jsoniter "github.com/json-iterator/go" + "github.com/mailru/easyjson" ) func BenchmarkEncodingJsonEncodeLargeStruct(b *testing.B) { @@ -28,6 +29,15 @@ func BenchmarkJsonIterEncodeLargeStruct(b *testing.B) { } } +func BenchmarkEasyJsonEncodeObjLarge(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if _, err := easyjson.Marshal(benchmarks.NewLargePayload()); err != nil { + b.Fatal(err) + } + } +} + func BenchmarkGoJayEncodeLargeStruct(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { diff --git a/benchmarks/encoder/encoder_bench_medium_test.go b/benchmarks/encoder/encoder_bench_medium_test.go @@ -8,6 +8,7 @@ import ( "github.com/francoispqt/gojay" "github.com/francoispqt/gojay/benchmarks" jsoniter "github.com/json-iterator/go" + "github.com/mailru/easyjson" ) func BenchmarkEncodingJsonEncodeMediumStruct(b *testing.B) { @@ -29,6 +30,15 @@ func BenchmarkJsonIterEncodeMediumStruct(b *testing.B) { } } +func BenchmarkEasyJsonEncodeObjMedium(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if _, err := easyjson.Marshal(benchmarks.NewMediumPayload()); err != nil { + b.Fatal(err) + } + } +} + func BenchmarkGoJayEncodeMediumStruct(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { diff --git a/benchmarks/encoder/encoder_bench_small_test.go b/benchmarks/encoder/encoder_bench_small_test.go @@ -8,6 +8,7 @@ import ( "github.com/francoispqt/gojay" "github.com/francoispqt/gojay/benchmarks" jsoniter "github.com/json-iterator/go" + "github.com/mailru/easyjson" ) func BenchmarkEncodingJsonEncodeSmallStruct(b *testing.B) { @@ -19,6 +20,15 @@ func BenchmarkEncodingJsonEncodeSmallStruct(b *testing.B) { } } +func BenchmarkEasyJsonEncodeObjSmall(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if _, err := easyjson.Marshal(benchmarks.NewSmallPayload()); err != nil { + b.Fatal(err) + } + } +} + func BenchmarkJsonIterEncodeSmallStruct(b *testing.B) { var json = jsoniter.ConfigCompatibleWithStandardLibrary b.ReportAllocs()