2
0
Fork 0
mirror of https://github.com/ii64/sonic.git synced 2026-06-20 16:45:22 +08:00

test: benchmark with github.com/goccy/go-json (#23)

chore: add benchmark result with go-json

Co-authored-by: duanyi.aster <duanyi.aster@bytedance.com>
This commit is contained in:
Yi Duan 2021-06-22 16:30:04 +08:00 committed by GitHub
parent 85a0d4219f
commit 936cee0d3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 191 additions and 20 deletions

View file

@ -6,30 +6,39 @@ A blazingly fast JSON serializing &amp; deserializing library, accelerated by JI
## Benchmarks
For all sizes of json and all scenes of usage, Sonic performs almost best.
- Small (400B, 11 keys, 3 levels)
- [Small](https://github.com/bytedance/sonic/blob/main/testdata/small.go) (400B, 11 keys, 3 levels)
![small benchmarks](bench-400B.png)
- Medium (110KB, 300+ keys, 3 levels, with many quoted-json values)
![medium benchmarks](bench-110KB.png)
- Large (550KB, 10000+ key, 6 levels)
- [Large](https://github.com/bytedance/sonic/blob/main/testdata/twitterescaped.json) (550KB, 10000+ key, 6 levels)
![large benchmarks](bench-550KB.png)
For a 13KB [TwitterJson](https://github.com/bytedance/sonic/blob/main/decoder/testdata_test.go#L19)(cpu i9-9880H, goarch amd64), Sonic is **1.5x** faster than [json-iterator](https://github.com/json-iterator/go) in decoding, **2.5x** faster in encoding.
For a 13KB [TwitterJson](https://github.com/bytedance/sonic/blob/main/decoder/testdata_test.go#L19), Sonic is **1.5x** faster than [json-iterator](https://github.com/json-iterator/go) in decoding, **2.5x** faster in encoding.
```powershell
BenchmarkDecoder_Generic_Sonic-16 10000 54309 ns/op 240.01 MB/s 46149 B/op 303 allocs/op
BenchmarkDecoder_Generic_StdLib-16 10000 135268 ns/op 96.36 MB/s 50899 B/op 772 allocs/op
BenchmarkDecoder_Generic_JsonIter-16 10000 96701 ns/op 134.80 MB/s 55791 B/op 1068 allocs/op
BenchmarkDecoder_Binding_Sonic-16 10000 29478 ns/op 442.20 MB/s 26062 B/op 34 allocs/op
BenchmarkDecoder_Binding_StdLib-16 10000 119348 ns/op 109.22 MB/s 10560 B/op 207 allocs/op
BenchmarkDecoder_Binding_JsonIter-16 10000 37646 ns/op 346.25 MB/s 14673 B/op 385 allocs/op
BenchmarkEncoder_Generic_Sonic-16 10000 25894 ns/op 503.39 MB/s 19096 B/op 42 allocs/op
BenchmarkEncoder_Generic_JsonIter-16 10000 50275 ns/op 259.27 MB/s 13432 B/op 77 allocs/op
BenchmarkEncoder_Generic_StdLib-16 10000 154901 ns/op 84.15 MB/s 48173 B/op 827 allocs/op
BenchmarkEncoder_Binding_Sonic-16 10000 7373 ns/op 1768.04 MB/s 13861 B/op 4 allocs/op
BenchmarkEncoder_Binding_JsonIter-16 10000 23223 ns/op 561.31 MB/s 9489 B/op 2 allocs/op
BenchmarkEncoder_Binding_StdLib-16 10000 19512 ns/op 668.07 MB/s 9477 B/op 1 allocs/op
goos: darwin
goarch: amd64
pkg: github.com/bytedance/sonic/encoder
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
BenchmarkEncoder_Generic_Sonic-16 100000 24174 ns/op 539.22 MB/s 17757 B/op 42 allocs/op
BenchmarkEncoder_Generic_JsonIter-16 100000 44613 ns/op 292.18 MB/s 13433 B/op 77 allocs/op
BenchmarkEncoder_Generic_GoJson-16 100000 87898 ns/op 148.30 MB/s 13234 B/op 39 allocs/op
BenchmarkEncoder_Generic_StdLib-16 100000 133512 ns/op 97.63 MB/s 48177 B/op 827 allocs/op
BenchmarkEncoder_Binding_Sonic-16 100000 6058 ns/op 2151.73 MB/s 13481 B/op 4 allocs/op
BenchmarkEncoder_Binding_JsonIter-16 100000 21223 ns/op 614.20 MB/s 9488 B/op 2 allocs/op
BenchmarkEncoder_Binding_GoJson-16 100000 10186 ns/op 1279.74 MB/s 9480 B/op 1 allocs/op
BenchmarkEncoder_Binding_StdLib-16 100000 17741 ns/op 734.75 MB/s 9479 B/op 1 allocs/op
BenchmarkDecoder_Generic_Sonic-16 100000 53344 ns/op 244.36 MB/s 50158 B/op 313 allocs/op
BenchmarkDecoder_Generic_StdLib-16 100000 141006 ns/op 92.44 MB/s 50898 B/op 772 allocs/op
BenchmarkDecoder_Generic_JsonIter-16 100000 106386 ns/op 122.53 MB/s 55785 B/op 1068 allocs/op
BenchmarkDecoder_Generic_GoJson-16 100000 107184 ns/op 121.61 MB/s 65678 B/op 944 allocs/op
BenchmarkDecoder_Binding_Sonic-16 100000 30039 ns/op 433.94 MB/s 25259 B/op 34 allocs/op
BenchmarkDecoder_Binding_StdLib-16 100000 131088 ns/op 99.44 MB/s 10560 B/op 207 allocs/op
BenchmarkDecoder_Binding_JsonIter-16 100000 37988 ns/op 343.13 MB/s 14674 B/op 385 allocs/op
BenchmarkDecoder_Binding_GoJson-16 100000 33741 ns/op 386.33 MB/s 22047 B/op 49 allocs/op
```
More detail see [ast/search_test.go](https://github.com/bytedance/sonic/blob/main/ast/search_test.go), [decoder/decoder_test.go](https://github.com/bytedance/sonic/blob/main/decoder/decoder_test.go), [encoder/encoder_test.go](https://github.com/bytedance/sonic/blob/main/encoder/encoder_test.go),
More detail see [decoder/decoder_test.go](https://github.com/bytedance/sonic/blob/main/decoder/decoder_test.go), [encoder/encoder_test.go](https://github.com/bytedance/sonic/blob/main/encoder/encoder_test.go), [ast/search_test.go](https://github.com/bytedance/sonic/blob/main/ast/search_test.go), [ast/parser_test.go](https://github.com/bytedance/sonic/blob/main/ast/parser_test.go)
## Usage
@ -119,7 +128,7 @@ For alignment to encoding/json, we provide API to pass `[]byte` as arguement, bu
```go
import "github.com/bytedance/sonic"
root, err := sonic.GetByString(_TwitterJson, "statuses", 3, "user")
root, err := sonic.GetFromString(_TwitterJson, "statuses", 3, "user")
a = root.GetByPath( "entities","description")
b = root.GetByPath( "entities","url")
c = root.GetByPath( "created_at")
@ -130,7 +139,7 @@ In most cases of fully-load generic json, `Unmarshal()` performs better than `as
```go
import "github.com/bytedance/sonic"
node, err := sonic.GetByString(_TwitterJson, "statuses", 3, "user")
node, err := sonic.GetFromString(_TwitterJson, "statuses", 3, "user")
var user interface{}
err = sonic.UnmarshalString(node.Raw(), &user)
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View file

@ -24,6 +24,7 @@ import (
`github.com/json-iterator/go`
`github.com/stretchr/testify/assert`
`github.com/stretchr/testify/require`
gojson `github.com/goccy/go-json`
)
var _BindingValue TwitterStruct
@ -111,6 +112,18 @@ func BenchmarkDecoder_Generic_JsonIter(b *testing.B) {
}
}
func BenchmarkDecoder_Generic_GoJson(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v interface{}
_ = gojson.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Binding_Sonic(b *testing.B) {
var w TwitterStruct
_, _ = decode(TwitterJson, &w)
@ -146,6 +159,18 @@ func BenchmarkDecoder_Binding_JsonIter(b *testing.B) {
}
}
func BenchmarkDecoder_Binding_GoJson(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var v TwitterStruct
_ = gojson.Unmarshal(m, &v)
}
}
func BenchmarkDecoder_Parallel_Generic_Sonic(b *testing.B) {
var w interface{}
_, _ = decode(TwitterJson, &w)
@ -187,6 +212,20 @@ func BenchmarkDecoder_Parallel_Generic_JsonIter(b *testing.B) {
})
}
func BenchmarkDecoder_Parallel_Generic_GoJson(b *testing.B) {
var w interface{}
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v interface{}
_ = gojson.Unmarshal(m, &v)
}
})
}
func BenchmarkDecoder_Parallel_Binding_Sonic(b *testing.B) {
var w TwitterStruct
_, _ = decode(TwitterJson, &w)
@ -227,3 +266,18 @@ func BenchmarkDecoder_Parallel_Binding_JsonIter(b *testing.B) {
}
})
}
func BenchmarkDecoder_Parallel_Binding_GoJson(b *testing.B) {
var w TwitterStruct
m := []byte(TwitterJson)
_ = gojson.Unmarshal(m, &w)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var v TwitterStruct
_ = gojson.Unmarshal(m, &v)
}
})
}

View file

@ -22,6 +22,7 @@ import (
`testing`
`github.com/json-iterator/go`
gojson `github.com/goccy/go-json`
`github.com/stretchr/testify/assert`
)
@ -128,6 +129,15 @@ func BenchmarkEncoder_Generic_JsonIter(b *testing.B) {
}
}
func BenchmarkEncoder_Generic_GoJson(b *testing.B) {
_, _ = gojson.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = gojson.Marshal(_GenericValue)
}
}
func BenchmarkEncoder_Generic_StdLib(b *testing.B) {
_, _ = json.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
@ -155,6 +165,15 @@ func BenchmarkEncoder_Binding_JsonIter(b *testing.B) {
}
}
func BenchmarkEncoder_Binding_GoJson(b *testing.B) {
_, _ = gojson.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = gojson.Marshal(&_BindingValue)
}
}
func BenchmarkEncoder_Binding_StdLib(b *testing.B) {
_, _ = json.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
@ -186,6 +205,17 @@ func BenchmarkEncoder_Parallel_Generic_JsonIter(b *testing.B) {
})
}
func BenchmarkEncoder_Parallel_Generic_GoJson(b *testing.B) {
_, _ = gojson.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = gojson.Marshal(_GenericValue)
}
})
}
func BenchmarkEncoder_Parallel_Generic_StdLib(b *testing.B) {
_, _ = json.Marshal(_GenericValue)
b.SetBytes(int64(len(TwitterJson)))
@ -219,6 +249,17 @@ func BenchmarkEncoder_Parallel_Binding_JsonIter(b *testing.B) {
})
}
func BenchmarkEncoder_Parallel_Binding_GoJson(b *testing.B) {
_, _ = gojson.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _ = gojson.Marshal(&_BindingValue)
}
})
}
func BenchmarkEncoder_Parallel_Binding_StdLib(b *testing.B) {
_, _ = json.Marshal(&_BindingValue)
b.SetBytes(int64(len(TwitterJson)))

1
go.mod
View file

@ -5,6 +5,7 @@ go 1.15
require (
github.com/chenzhuoyu/base64x v0.0.0-20210528162528-3c6c11c43ee5
github.com/davecgh/go-spew v1.1.1
github.com/goccy/go-json v0.7.1 // indirect
github.com/json-iterator/go v1.1.10
github.com/klauspost/cpuid/v2 v2.0.6
github.com/stretchr/testify v1.7.0

2
go.sum
View file

@ -3,6 +3,8 @@ github.com/chenzhuoyu/base64x v0.0.0-20210528162528-3c6c11c43ee5/go.mod h1:NfDzX
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/goccy/go-json v0.7.1 h1:VMhnh5gcc8De8f6m2DLvSqY1x8Jwl3btet+EqMP0QNs=
github.com/goccy/go-json v0.7.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=

64
testdata/small.go vendored Normal file
View file

@ -0,0 +1,64 @@
/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package testdata
// ffjson: skip
// easyjson:skip
type Book struct {
BookId int `json:"id"`
BookIds []int `json:"ids"`
Title string `json:"title"`
Titles []string `json:"titles"`
Price float64 `json:"price"`
Prices []float64 `json:"prices"`
Hot bool `json:"hot"`
Hots []bool `json:"hots"`
Author Author `json:"author"`
Authors []Author `json:"authors"`
Weights []int `json:"weights"`
}
// ffjson: skip
// easyjson:skip
type Author struct {
Name string `json:"name"`
Age int `json:"age"`
Male bool `json:"male"`
}
var book = Book{
BookId: 12125925,
BookIds: []int{-2147483648, 2147483647},
Title: "未来简史-从智人到智神",
Titles: []string{"hello", "world"},
Price: 40.8,
Prices: []float64{-0.1, 0.1},
Hot: true,
Hots: []bool{true, true, true},
Author: author,
Authors: []Author{author, author, author},
Weights: nil,
}
var author = Author{
Name: "json",
Age: 99,
Male: true,
}
var data = []byte(`{"id":12125925,"ids":[-2147483648,2147483647],"title":"未来简史-从智人到智神","titles":["hello","world"],"price":40.8,"prices":[-0.1,0.1],"hot":true,"hots":[true,true,true],"author":{"name":"json","age":99,"male":true},"authors":[{"name":"json","age":99,"male":true},{"name":"json","age":99,"male":true},{"name":"json","age":99,"male":true}],"weights":[]}`)