2
0
Fork 0
mirror of https://github.com/ii64/sonic.git synced 2026-06-21 00:46:43 +08:00

doc: update readme (#143)

* doc: update readme

* test: add SetOne_XX() benchmarks

* doc: update bechmark charts

* doc: fix possible typos

Co-authored-by: liuqiang <liuqiang.06@bytedance.com>
Co-authored-by: duanyi.aster <duanyi.aster@bytedance.com>
This commit is contained in:
liu 2021-12-01 18:03:19 +08:00 committed by GitHub
parent 49df11ef83
commit 3f2bab552b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 459 additions and 205 deletions

136
README.md
View file

@ -3,7 +3,7 @@
A blazingly fast JSON serializing &amp; deserializing library, accelerated by JIT (just-in-time compiling) and SIMD (single-instruction-multiple-data).
## Requirement
- Go 1.15/1.16
- Go 1.15/1.16/1.17
- Linux/darwin OS
- Amd64 CPU with AVX instruction set
@ -13,65 +13,67 @@ A blazingly fast JSON serializing &amp; deserializing library, accelerated by JI
- Fast, fast, fast!
## Benchmarks
For **all sizes** of json and **all cases** of usage, **Sonic performs best**.
- [Small](https://github.com/bytedance/sonic/blob/main/testdata/small.go) (400B, 11 keys, 3 layers)
![small benchmarks](bench-small.png)
- [Large](https://github.com/bytedance/sonic/blob/main/testdata/twitter.json) (635KB, 10000+ key, 6 layers)
![large benchmarks](bench-large.png)
For **all sizes** of json and **all scenarios** of usage, **Sonic performs best**.
- [Medium](https://github.com/bytedance/sonic/blob/main/decoder/testdata_test.go#L19) (13KB, 300+ key, 6 layers)
**For medium data, Sonic's speed is `2.6x times` of [json-iterator's](https://github.com/json-iterator/go) in `decoding`, `2.5x times` in `encoding`and `8.3x times` in `searching`.**
```powershell
goversion: 1.17.1
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
BenchmarkEncoder_Generic_Sonic-16 100000 25547 ns/op 510.23 MB/s 13762 B/op 4 allocs/op
BenchmarkEncoder_Generic_JsonIter-16 100000 44526 ns/op 292.75 MB/s 13433 B/op 77 allocs/op
BenchmarkEncoder_Generic_StdLib-16 100000 134480 ns/op 96.93 MB/s 48177 B/op 827 allocs/op
BenchmarkEncoder_Binding_Sonic-16 100000 6658 ns/op 1957.74 MB/s 14156 B/op 4 allocs/op
BenchmarkEncoder_Binding_JsonIter-16 100000 21367 ns/op 610.05 MB/s 9487 B/op 2 allocs/op
BenchmarkEncoder_Binding_StdLib-16 100000 17558 ns/op 742.41 MB/s 9480 B/op 1 allocs/op
BenchmarkEncoder_Parallel_Generic_Sonic-16 100000 4562 ns/op 2857.18 MB/s 10957 B/op 4 allocs/op
BenchmarkEncoder_Parallel_Generic_JsonIter-16 100000 10943 ns/op 1191.21 MB/s 13449 B/op 77 allocs/op
BenchmarkEncoder_Parallel_Generic_StdLib-16 100000 52174 ns/op 249.84 MB/s 48218 B/op 827 allocs/op
BenchmarkEncoder_Parallel_Binding_Sonic-16 100000 1422 ns/op 9168.12 MB/s 11030 B/op 4 allocs/op
BenchmarkEncoder_Parallel_Binding_JsonIter-16 100000 4630 ns/op 2815.35 MB/s 9496 B/op 2 allocs/op
BenchmarkEncoder_Parallel_Binding_StdLib-16 100000 4977 ns/op 2619.08 MB/s 9488 B/op 1 allocs/op
BenchmarkEncoder_Generic_Sonic 25181 ns/op 517.65 MB/s 13035 B/op 4 allocs/op
BenchmarkEncoder_Generic_JsonIter 43765 ns/op 297.84 MB/s 13433 B/op 77 allocs/op
BenchmarkEncoder_Generic_StdLib 108776 ns/op 119.83 MB/s 49137 B/op 827 allocs/op
BenchmarkEncoder_Binding_Sonic 6282 ns/op 2075.01 MB/s 13765 B/op 4 allocs/op
BenchmarkEncoder_Binding_JsonIter 20740 ns/op 628.51 MB/s 9487 B/op 2 allocs/op
BenchmarkEncoder_Binding_StdLib 16661 ns/op 782.34 MB/s 9479 B/op 1 allocs/op
BenchmarkEncoder_Parallel_Generic_Sonic-16 4072 ns/op 3200.89 MB/s 11052 B/op 4 allocs/op
BenchmarkEncoder_Parallel_Generic_JsonIter-16 11379 ns/op 1145.52 MB/s 13458 B/op 77 allocs/op
BenchmarkEncoder_Parallel_Generic_StdLib-16 50635 ns/op 257.43 MB/s 49183 B/op 827 allocs/op
BenchmarkEncoder_Parallel_Binding_Sonic-16 1304 ns/op 9994.64 MB/s 10925 B/op 4 allocs/op
BenchmarkEncoder_Parallel_Binding_JsonIter-16 6072 ns/op 2146.76 MB/s 9505 B/op 2 allocs/op
BenchmarkEncoder_Parallel_Binding_StdLib-16 3510 ns/op 3713.89 MB/s 9481 B/op 1 allocs/op
BenchmarkDecoder_Generic_Sonic-16 100000 57247 ns/op 227.70 MB/s 49727 B/op 313 allocs/op
BenchmarkDecoder_Generic_StdLib-16 100000 139698 ns/op 93.31 MB/s 50898 B/op 772 allocs/op
BenchmarkDecoder_Generic_JsonIter-16 100000 101967 ns/op 127.84 MB/s 55787 B/op 1068 allocs/op
BenchmarkDecoder_Binding_Sonic-16 100000 28254 ns/op 461.35 MB/s 25062 B/op 34 allocs/op
BenchmarkDecoder_Binding_StdLib-16 100000 123779 ns/op 105.31 MB/s 10560 B/op 207 allocs/op
BenchmarkDecoder_Binding_JsonIter-16 100000 38253 ns/op 340.75 MB/s 14674 B/op 385 allocs/op
BenchmarkDecoder_Parallel_Generic_Sonic-16 100000 10171 ns/op 1281.59 MB/s 49458 B/op 313 allocs/op
BenchmarkDecoder_Parallel_Generic_StdLib-16 100000 54916 ns/op 237.36 MB/s 50907 B/op 772 allocs/op
BenchmarkDecoder_Parallel_Generic_JsonIter-16 100000 48286 ns/op 269.95 MB/s 55811 B/op 1068 allocs/op
BenchmarkDecoder_Parallel_Binding_Sonic-16 100000 5282 ns/op 2467.83 MB/s 24683 B/op 34 allocs/op
BenchmarkDecoder_Parallel_Binding_StdLib-16 100000 31875 ns/op 408.94 MB/s 10559 B/op 207 allocs/op
BenchmarkDecoder_Parallel_Binding_JsonIter-16 100000 13810 ns/op 943.90 MB/s 14679 B/op 385 allocs/op
BenchmarkDecoder_Generic_Sonic 53843 ns/op 242.09 MB/s 49779 B/op 313 allocs/op
BenchmarkDecoder_Generic_StdLib 130402 ns/op 99.96 MB/s 50868 B/op 772 allocs/op
BenchmarkDecoder_Generic_JsonIter 92810 ns/op 140.45 MB/s 55788 B/op 1068 allocs/op
BenchmarkDecoder_Binding_Sonic 29793 ns/op 437.52 MB/s 24778 B/op 34 allocs/op
BenchmarkDecoder_Binding_StdLib 121206 ns/op 107.54 MB/s 10576 B/op 208 allocs/op
BenchmarkDecoder_Binding_JsonIter 36099 ns/op 361.09 MB/s 14674 B/op 385 allocs/op
BenchmarkDecoder_Parallel_Generic_Sonic-16 10319 ns/op 1263.21 MB/s 49423 B/op 313 allocs/op
BenchmarkDecoder_Parallel_Generic_StdLib-16 58526 ns/op 222.72 MB/s 50875 B/op 772 allocs/op
BenchmarkDecoder_Parallel_Generic_JsonIter-16 60156 ns/op 216.69 MB/s 55812 B/op 1068 allocs/op
BenchmarkDecoder_Parallel_Binding_Sonic-16 7265 ns/op 1794.18 MB/s 24952 B/op 34 allocs/op
BenchmarkDecoder_Parallel_Binding_StdLib-16 44000 ns/op 296.25 MB/s 10575 B/op 208 allocs/op
BenchmarkDecoder_Parallel_Binding_JsonIter-16 21029 ns/op 619.86 MB/s 14678 B/op 385 allocs/op
BenchmarkSearchOne_Gjson-16 100000 8992 ns/op 1448.28 MB/s 0 B/op 0 allocs/op
BenchmarkSearchOne_Jsoniter-16 100000 58313 ns/op 223.33 MB/s 27936 B/op 647 allocs/op
BenchmarkSearchOne_Sonic-16 100000 10497 ns/op 1240.61 MB/s 29 B/op 1 allocs/op
BenchmarkSearchOne_Parallel_Gjson-16 100000 1046 ns/op 12449.59 MB/s 0 B/op 0 allocs/op
BenchmarkSearchOne_Parallel_Jsoniter-16 100000 16080 ns/op 809.88 MB/s 27942 B/op 647 allocs/op
BenchmarkSearchOne_Parallel_Sonic-16 100000 1435 ns/op 9074.18 MB/s 285 B/op 1 allocs/op
BenchmarkGetOne_Sonic 17070 ns/op 762.94 MB/s 29 B/op 1 allocs/op
BenchmarkGetOne_Gjson 19714 ns/op 660.59 MB/s 0 B/op 0 allocs/op
BenchmarkGetOne_Jsoniter 99281 ns/op 131.17 MB/s 27936 B/op 647 allocs/op
BenchmarkSetOne_Sonic 23730 ns/op 548.80 MB/s 1883 B/op 17 allocs/op
BenchmarkSetOne_Sjson 57680 ns/op 225.78 MB/s 52180 B/op 9 allocs/op
BenchmarkSetOne_Jsoniter 104018 ns/op 125.20 MB/s 45859 B/op 964 allocs/op
BenchmarkGetOne_Parallel_Sonic-16 2010 ns/op 6479.41 MB/s 114 B/op 1 allocs/op
BenchmarkGetOne_Parallel_Gjson-16 1815 ns/op 7176.39 MB/s 0 B/op 0 allocs/op
BenchmarkGetOne_Parallel_Jsoniter-16 23261 ns/op 559.86 MB/s 27942 B/op 647 allocs/op
BenchmarkSetOne_Parallel_Sonic-16 2007 ns/op 6487.78 MB/s 2202 B/op 17 allocs/op
BenchmarkSetOne_Parallel_Sjson-16 12422 ns/op 1048.40 MB/s 52180 B/op 9 allocs/op
BenchmarkSetOne_Parallel_Jsoniter-16 39204 ns/op 332.18 MB/s 45889 B/op 964 allocs/op
```
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), [ast/node_test.go](https://github.com/bytedance/sonic/blob/main/ast/node_test.go)
- [Small](https://github.com/bytedance/sonic/blob/main/testdata/small.go) (400B, 11 keys, 3 layers)
![small benchmarks](bench-small.jpg)
- [Large](https://github.com/bytedance/sonic/blob/main/testdata/twitter.json) (635KB, 10000+ key, 6 layers)
![large benchmarks](bench-large.jpg)
See [bench.sh](https://github.com/bytedance/sonic/blob/main/bench.sh) for benchmark codes.
## How it works
See [INTRODUCTION.md](INTRODUCTION.md)
## Fuzzing
[sonic-fuzz](https://github.com/liuq19/sonic-fuzz) is the repository for fuzzing tests. If you find any bug, please report the issue to sonic.
See [INTRODUCTION.md](INTRODUCTION.md).
## Usage
### Marshal/Unmarshal
The behaviors are mostly consistent with encoding/json, except some uncommon escaping (see [issue4](https://github.com/bytedance/sonic/issues/4))
Their behaviors are mostly consistent with `encoding/json`, except two escaping form (see [issue4](https://github.com/bytedance/sonic/issues/4)) that is **NOT** in conformity to [RFC8259](https://datatracker.ietf.org/doc/html/rfc8259).
```go
import "github.com/bytedance/sonic"
@ -118,7 +120,6 @@ import "github.com/bytedance/sonic/encoder"
m := map[string]interface{}{}
v, err := encoder.Encode(m, encoder.SortMapKeys)
```
**Caution**: sonic encode struct in order of its original field declaration, so if you want to sort a struct's keys like the map's, just rewrite your struct.
### Print Syntax Error
```go
@ -211,20 +212,23 @@ Since Sonic uses [golang-asm](https://github.com/twitchyliquid64/golang-asm) as
import (
"reflect"
"github.com/bytedance/sonic"
)
func init() {
var v HugeStruct
err := sonic.Pretouch(reflect.TypeOf(v))
}
"github.com/bytedance/sonic/option"
)
func init() {
var v HugeStruct
// For most large types (nesting depth <= 5)
err := sonic.Pretouch(reflect.TypeOf(v))
// If the type is too deep nesting (nesting depth > 5),
// you can set compile recursive depth in Pretouch for better stability in JIT.
err := sonic.Pretouch(reflect.TypeOf(v), option.WithCompileRecursiveDepth(depth))
```
**CAUTION:** use the **STRUCT instead of its POINTER** to `Pretouch()`, otherwise it won't work when you pass the pointer to `Marshal()/Unmarshal()`!
### Pass string or []byte?
For alignment to encoding/json, we provide API to pass `[]byte` as argument, but the string-to-bytes copy is conducted at the same time considering safety, which may lose performance when origin JSON is huge. Therefore, you can use `UnmarshalString`, `GetFromString` to pass a string, as long as your origin data is a string or **nocopy-cast** is safe for your []byte.
For alignment to `encoding/json`, we provide API to pass `[]byte` as an argument, but the string-to-bytes copy is conducted at the same time considering safety, which may lose performance when origin JSON is huge. Therefore, you can use `UnmarshalString` and `GetFromString` to pass a string, as long as your origin data is a string or **nocopy-cast** is safe for your []byte.
### Better performance for generic deserializing
In most cases, `Unmarshal()` with schemalized data performs better than `ast.Loads()`/`node.Interface()` with generic data. But if you only have a schema for partial json, you can combine `Get()` and `Unmarshal()` together:
### Better performance for generic data
In **fully-parsed** scenario, `Unmarshal()` performs better than `Get()`+`Node.Interface()`. But if you only have a part of schema for specific json, you can combine `Get()` and `Unmarshal()` together:
```go
import "github.com/bytedance/sonic"
@ -232,14 +236,20 @@ node, err := sonic.GetFromString(_TwitterJson, "statuses", 3, "user")
var user User // your partial schema...
err = sonic.UnmarshalString(node.Raw(), &user)
```
Even if you don't have any schema, Use `InterfaceUseNode()` as the container of generic values instead of `Map()` or `Interface()`:
Even if you don't have any schema, use `ast.Node` as the container of generic values instead of `map` or `interface`:
```go
import "github.com/bytedance/sonic"
node, err := sonic.GetFromString(_TwitterJson, "statuses", 3, "user")
user := node.InterfaceUseNode() // use node.Interface() as little as possible
root, err := sonic.GetFromString(_TwitterJson)
user := root.GetByPath("statuses", 3, "user") // === root.Get("status").Index(3).Get("user")
err = user.Check()
// err = user.LoadAll() // only call this when you want to use 'user' concurrently...
go someFunc(user)
```
Why?
1. using `Interface()` means Sonic must parse all the underlying values, while in most cases you only need several of them;
2. `map[x]` is not efficient enough compared to `array[x]`, but `ast.Node` can use `Index()`, for either array or object node;
3. `map`'s performance degrades a lot once rehashing triggered, but `ast.Node` doesn't has this concern;
Why? Because `ast.Node` stores its children using `array`:
- `Map`'s performance degrades a lot once rehashing triggered, but `ast.Node` doesn't have this concern;
- **Hashing** (`map[x]`) is not as efficient as **Indexing** (`array[x]`), which `ast.Node` can conduct on **both array and object**.
- Using `Interface()`/`Map()` means Sonic must parse all the underlying values, while in most cases you don't need them all;
**CAUTION:** `ast.Node` **DOESN'T** ensure concurrent security directly, due to its **lazy-load** design. However, your can call `Node.Load()`/`Node.LoadAll()` to achieve that, which may bring performance reduction while it still works faster than converting to `map` or `interface{}`

View file

@ -24,12 +24,9 @@ import (
`testing`
`github.com/bytedance/sonic/internal/native/types`
jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/assert`
)
var parallelism = 4
func TestLoadAll(t *testing.T) {
e := Node{}
err := e.Load()
@ -770,7 +767,6 @@ func TestNodeAdd(t *testing.T) {
func BenchmarkLoadNode(b *testing.B) {
b.Run("Interface()", func(b *testing.B) {
b.SetParallelism(parallelism)
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
@ -785,7 +781,6 @@ func BenchmarkLoadNode(b *testing.B) {
})
b.Run("LoadAll()", func(b *testing.B) {
b.SetParallelism(parallelism)
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
@ -800,7 +795,6 @@ func BenchmarkLoadNode(b *testing.B) {
})
b.Run("InterfaceUseNode()", func(b *testing.B) {
b.SetParallelism(parallelism)
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
@ -815,7 +809,6 @@ func BenchmarkLoadNode(b *testing.B) {
})
b.Run("Load()", func(b *testing.B) {
b.SetParallelism(parallelism)
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
@ -836,7 +829,6 @@ func BenchmarkNodeGetByPath(b *testing.B) {
b.Fatalf("decode failed: %v", derr.Error())
}
_, _ = root.GetByPath("statuses", 3, "entities", "hashtags", 0, "text").String()
b.SetParallelism(parallelism)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
@ -846,14 +838,13 @@ func BenchmarkNodeGetByPath(b *testing.B) {
})
}
func BenchmarkStructGetByPath_Jsoniter(b *testing.B) {
func BenchmarkStructGetByPath(b *testing.B) {
var root = _TwitterStruct{}
err := jsoniter.Unmarshal([]byte(_TwitterJson), &root)
err := json.Unmarshal([]byte(_TwitterJson), &root)
if err != nil {
b.Fatalf("unmarshal failed: %v", err)
}
b.SetParallelism(parallelism)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
@ -976,7 +967,6 @@ func BenchmarkNodeSet(b *testing.B) {
node.Set("test4", NewNumber("4"))
node.Set("test5", NewNumber("5"))
n := NewNull()
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
node.Set("test3", n)
@ -996,7 +986,6 @@ func BenchmarkMapSet(b *testing.B) {
node.Set("test5", NewNumber("5"))
m, _ := node.Map()
n := NewNull()
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
m["test3"] = n
@ -1015,7 +1004,6 @@ func BenchmarkNodeSetByIndex(b *testing.B) {
node.Add(NewNumber("4"))
node.Add(NewNumber("5"))
n := NewNull()
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
node.SetByIndex(2, n)
@ -1035,7 +1023,6 @@ func BenchmarkSliceSetByIndex(b *testing.B) {
node.Add(NewNumber("5"))
m, _ := node.Array()
n := NewNull()
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
m[2] = n
@ -1069,7 +1056,6 @@ func BenchmarkNodeUnset(b *testing.B) {
node.Set("test3", NewNumber("3"))
node.Set("test4", NewNumber("4"))
node.Set("test5", NewNumber("5"))
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
node.Unset("test3")
@ -1088,7 +1074,6 @@ func BenchmarkMapUnset(b *testing.B) {
node.Set("test4", NewNumber("4"))
node.Set("test5", NewNumber("5"))
m, _ := node.Map()
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
delete(m, "test3")
@ -1106,7 +1091,6 @@ func BenchmarkNodUnsetByIndex(b *testing.B) {
node.Add(NewNumber("3"))
node.Add(NewNumber("4"))
node.Add(NewNumber("5"))
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
node.UnsetByIndex(2)
@ -1125,7 +1109,6 @@ func BenchmarkSliceUnsetByIndex(b *testing.B) {
node.Add(NewNumber("4"))
node.Add(NewNumber("5"))
m, _ := node.Array()
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
for i:=3; i<5; i++ {
@ -1136,7 +1119,6 @@ func BenchmarkSliceUnsetByIndex(b *testing.B) {
func BenchmarkNodeAdd(b *testing.B) {
n := NewObject([]Pair{{"test", NewNumber("1")}})
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
node := NewArray([]Node{})
@ -1146,7 +1128,6 @@ func BenchmarkNodeAdd(b *testing.B) {
func BenchmarkSliceAdd(b *testing.B) {
n := NewObject([]Pair{{"test", NewNumber("1")}})
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
node := []Node{}
@ -1156,7 +1137,6 @@ func BenchmarkSliceAdd(b *testing.B) {
func BenchmarkMapAdd(b *testing.B) {
n := NewObject([]Pair{{"test", NewNumber("1")}})
b.SetParallelism(parallelism)
b.ResetTimer()
for i := 0; i < b.N; i++ {
node := map[string]Node{}

View file

@ -240,52 +240,95 @@ func TestParsehNotExist(t *testing.T) {
}
}
func BenchmarkParser_StdLib(b *testing.B) {
var bv = []byte(_TwitterJson)
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var out interface{}
_ = json.Unmarshal(bv, &out)
}
}
func BenchmarkParser_JsonIter(b *testing.B) {
var bv = []byte(_TwitterJson)
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var out interface{}
_ = jsoniter.Unmarshal(bv, &out)
}
}
func BenchmarkParser_Sonic(b *testing.B) {
_, _, _ = Loads(_TwitterJson)
r, err := NewParser(_TwitterJson).Parse()
if err != 0 {
b.Fatal(err)
}
if err := r.LoadAll(); err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _, _ = Loads(_TwitterJson)
r, _ = NewParser(_TwitterJson).Parse()
_ = r.LoadAll()
}
}
func BenchmarkParser_Parallel_StdLib(b *testing.B) {
var bv = []byte(_TwitterJson)
func BenchmarkParser_Gjson(b *testing.B) {
gjson.Parse(_TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
gjson.Parse(_TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
}
}
func BenchmarkParser_Jsoniter(b *testing.B) {
v := jsoniter.Get([]byte(_TwitterJson)).GetInterface()
if v == nil {
b.Fatal(v)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = jsoniter.Get([]byte(_TwitterJson)).GetInterface()
}
}
func BenchmarkParser_Parallel_Sonic(b *testing.B) {
r, _ := NewParser(_TwitterJson).Parse()
if err := r.LoadAll(); err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(_TwitterJson)))
b.SetParallelism(parallelism)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
var out interface{}
_ = json.Unmarshal(bv, &out)
r, _ := NewParser(_TwitterJson).Parse()
_ = r.LoadAll()
}
})
}
func BenchmarkParser_Parallel_JsonIter(b *testing.B) {
func BenchmarkParser_Parallel_Gjson(b *testing.B) {
gjson.Parse(_TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
return true
})
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
gjson.Parse(_TwitterJson).ForEach(func(key, value gjson.Result) bool {
if !value.Exists() {
b.Fatal(value.Index)
}
_ = value.Value()
return true
})
}
})
}
func BenchmarkParser_Parallel_Jsoniter(b *testing.B) {
var bv = []byte(_TwitterJson)
b.SetBytes(int64(len(_TwitterJson)))
b.SetParallelism(parallelism)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
@ -295,98 +338,215 @@ func BenchmarkParser_Parallel_JsonIter(b *testing.B) {
})
}
func BenchmarkParser_Parallel_Sonic(b *testing.B) {
_, _, _ = Loads(_TwitterJson)
func BenchmarkParseOne_Sonic(b *testing.B) {
ast, _ := NewParser(_TwitterJson).Parse()
node, _ := ast.Get("statuses").Index(2).Get("id").Int64()
if node != 249289491129438208 {
b.Fail()
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast, _ := NewParser(_TwitterJson).Parse()
_, _ = ast.Get("statuses").Index(2).Get("id").Int64()
}
}
func BenchmarkParseOne_Gjson(b *testing.B) {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.2.id")
v := node.Int()
if v != 249289491129438208 {
b.Fatal(node)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.2.id")
_ = node.Int()
}
}
func BenchmarkParseOne_Jsoniter(b *testing.B) {
data := []byte(_TwitterJson)
ast := jsoniter.Get(data, "statuses", 2, "id")
node := ast.ToInt()
if node != 249289491129438208 {
b.Fail()
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data, "statuses", 2, "id")
_ = ast.ToInt()
}
}
func BenchmarkParseOne_Parallel_Sonic(b *testing.B) {
ast, _ := NewParser(_TwitterJson).Parse()
node, _ := ast.Get("statuses").Index(2).Get("id").Int64()
if node != 249289491129438208 {
b.Fail()
}
b.SetBytes(int64(len(_TwitterJson)))
b.SetParallelism(parallelism)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, _, _ = Loads(_TwitterJson)
ast, _ := NewParser(_TwitterJson).Parse()
_, _ = ast.Get("statuses").Index(2).Get("id").Int64()
}
})
}
func BenchmarkGetOne_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
for i := 0; i < b.N; i++ {
ast := gjson.Get(_TwitterJson, "statuses.2.id")
node := ast.Int()
if node != 249289491129438208 {
b.Fatal(node)
}
func BenchmarkParseOne_Parallel_Gjson(b *testing.B) {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.2.id")
v := node.Int()
if v != 249289491129438208 {
b.Fatal(node)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.2.id")
_ = node.Int()
}
})
}
func BenchmarkGetOne_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
func BenchmarkParseOne_Parallel_Jsoniter(b *testing.B) {
data := []byte(_TwitterJson)
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data, "statuses", 2, "id")
node := ast.ToInt()
if node != 249289491129438208 {
b.Fail()
}
ast := jsoniter.Get(data, "statuses", 2, "id")
node := ast.ToInt()
if node != 249289491129438208 {
b.Fail()
}
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data := []byte(_TwitterJson)
ast := jsoniter.Get(data, "statuses", 2, "id")
_ = ast.ToInt()
}
})
}
func BenchmarkGetOne_Sonic(b *testing.B) {
func BenchmarkParseSeven_Sonic(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast, _ := NewParser(_TwitterJson).Parse()
node, _ := ast.Get("statuses").Index(2).Get("id").Int64()
if node != 249289491129438208 {
b.Fail()
}
}
}
func BenchmarkGetSeven_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
for i := 0; i < b.N; i++ {
ast := gjson.Get(_TwitterJson, "statuses.3.id")
ast = gjson.Get(_TwitterJson, "statuses.3.user.entities.description")
ast = gjson.Get(_TwitterJson, "statuses.3.user.entities.url.urls")
ast = gjson.Get(_TwitterJson, "statuses.3.user.entities.url")
ast = gjson.Get(_TwitterJson, "statuses.3.user.created_at")
ast = gjson.Get(_TwitterJson, "statuses.3.user.name")
ast = gjson.Get(_TwitterJson, "statuses.3.text")
if ast.Value() == nil {
b.Fail()
}
}
}
func BenchmarkGetSeven_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
data := []byte(_TwitterJson)
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data, "statuses", 3, "id")
ast = jsoniter.Get(data, "statuses", 3, "user", "entities","description")
ast = jsoniter.Get(data, "statuses", 3, "user", "entities","url","urls")
ast = jsoniter.Get(data, "statuses", 3, "user", "entities","url")
ast = jsoniter.Get(data, "statuses", 3, "user", "created_at")
ast = jsoniter.Get(data, "statuses", 3, "user", "name")
ast = jsoniter.Get(data, "statuses", 3, "text")
if ast == nil {
b.Fail()
}
}
}
func BenchmarkGetSeven_SonicParser(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
for i := 0; i < b.N; i++ {
ast, _ := NewParser(_TwitterJson).Parse()
node := ast.GetByPath( "statuses", 3, "id")
node := ast.GetByPath("statuses", 3, "id")
node = ast.GetByPath("statuses", 3, "user", "entities","description")
node = ast.GetByPath("statuses", 3, "user", "entities","url","urls")
node = ast.GetByPath("statuses", 3, "user", "entities","url","urls")
node = ast.GetByPath("statuses", 3, "user", "entities","url")
node = ast.GetByPath("statuses", 3, "user", "created_at")
node = ast.GetByPath("statuses", 3, "user", "name")
node = ast.GetByPath("statuses", 3, "text")
if node == nil {
if node.Check() != nil {
b.Fail()
}
}
}
func BenchmarkParseSeven_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.3.id")
node = ast.Get( "statuses.3.user.entities.description")
node = ast.Get( "statuses.3.user.entities.url.urls")
node = ast.Get( "statuses.3.user.entities.url")
node = ast.Get( "statuses.3.user.created_at")
node = ast.Get( "statuses.3.user.name")
node = ast.Get( "statuses.3.text")
if node.Value() == nil {
b.Fail()
}
}
}
func BenchmarkParseSeven_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
data := []byte(_TwitterJson)
for i := 0; i < b.N; i++ {
ast := jsoniter.Get(data)
node := ast.Get("statuses", 3, "id")
node = ast.Get("statuses", 3, "user", "entities","description")
node = ast.Get("statuses", 3, "user", "entities","url","urls")
node = ast.Get("statuses", 3, "user", "entities","url")
node = ast.Get("statuses", 3, "user", "created_at")
node = ast.Get("statuses", 3, "user", "name")
node = ast.Get("statuses", 3, "text")
if node.LastError() != nil {
b.Fail()
}
}
}
func BenchmarkParseSeven_Parallel_Sonic(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast, _ := NewParser(_TwitterJson).Parse()
node := ast.GetByPath("statuses", 3, "id")
node = ast.GetByPath("statuses", 3, "user", "entities","description")
node = ast.GetByPath("statuses", 3, "user", "entities","url","urls")
node = ast.GetByPath("statuses", 3, "user", "entities","url")
node = ast.GetByPath("statuses", 3, "user", "created_at")
node = ast.GetByPath("statuses", 3, "user", "name")
node = ast.GetByPath("statuses", 3, "text")
if node.Check() != nil {
b.Fail()
}
}
})
}
func BenchmarkParseSeven_Parallel_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Parse(_TwitterJson)
node := ast.Get("statuses.3.id")
node = ast.Get( "statuses.3.user.entities.description")
node = ast.Get( "statuses.3.user.entities.url.urls")
node = ast.Get( "statuses.3.user.entities.url")
node = ast.Get( "statuses.3.user.created_at")
node = ast.Get( "statuses.3.user.name")
node = ast.Get( "statuses.3.text")
if node.Value() == nil {
b.Fail()
}
}
})
}
func BenchmarkParseSeven_Parallel_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
data := []byte(_TwitterJson)
ast := jsoniter.Get(data)
node := ast.Get("statuses", 3, "id")
node = ast.Get("statuses", 3, "user", "entities","description")
node = ast.Get("statuses", 3, "user", "entities","url","urls")
node = ast.Get("statuses", 3, "user", "entities","url")
node = ast.Get("statuses", 3, "user", "created_at")
node = ast.Get("statuses", 3, "user", "name")
node = ast.Get("statuses", 3, "text")
if node.LastError() != nil {
b.Fail()
}
}
})
}

View file

@ -21,7 +21,11 @@ import (
`runtime`
`runtime/debug`
`sync`
`fmt`
`math`
`strconv`
`github.com/tidwall/sjson`
jsoniter `github.com/json-iterator/go`
`github.com/stretchr/testify/assert`
`github.com/tidwall/gjson`
@ -190,7 +194,7 @@ func TestSearchNotExist(t *testing.T) {
}
}
func BenchmarkSearchOne_Gjson(b *testing.B) {
func BenchmarkGetOne_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
for i := 0; i < b.N; i++ {
ast := gjson.Get(_TwitterJson, "statuses.3.id")
@ -201,7 +205,7 @@ func BenchmarkSearchOne_Gjson(b *testing.B) {
}
}
func BenchmarkSearchOne_Jsoniter(b *testing.B) {
func BenchmarkGetOne_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
data := []byte(_TwitterJson)
for i := 0; i < b.N; i++ {
@ -213,7 +217,7 @@ func BenchmarkSearchOne_Jsoniter(b *testing.B) {
}
}
func BenchmarkSearchOne_Sonic(b *testing.B) {
func BenchmarkGetOne_Sonic(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
ast := NewSearcher(_TwitterJson)
for i := 0; i < b.N; i++ {
@ -228,9 +232,8 @@ func BenchmarkSearchOne_Sonic(b *testing.B) {
}
}
func BenchmarkSearchOne_Parallel_Gjson(b *testing.B) {
func BenchmarkGetOne_Parallel_Gjson(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := gjson.Get(_TwitterJson, "statuses.3.id")
@ -242,10 +245,9 @@ func BenchmarkSearchOne_Parallel_Gjson(b *testing.B) {
})
}
func BenchmarkSearchOne_Parallel_Jsoniter(b *testing.B) {
func BenchmarkGetOne_Parallel_Jsoniter(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
data := []byte(_TwitterJson)
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ast := jsoniter.Get(data, "statuses", 3, "id")
@ -257,9 +259,8 @@ func BenchmarkSearchOne_Parallel_Jsoniter(b *testing.B) {
})
}
func BenchmarkSearchOne_Parallel_Sonic(b *testing.B) {
func BenchmarkGetOne_Parallel_Sonic(b *testing.B) {
b.SetBytes(int64(len(_TwitterJson)))
b.SetParallelism(parallelism)
b.RunParallel(func(pb *testing.PB) {
ast := NewSearcher(_TwitterJson)
for pb.Next() {
@ -274,3 +275,107 @@ func BenchmarkSearchOne_Parallel_Sonic(b *testing.B) {
}
})
}
func BenchmarkSetOne_Sonic(b *testing.B) {
node, err := NewSearcher(_TwitterJson).GetByPath("statuses", 3)
if err != nil {
b.Fatal(err)
}
n := NewNumber(strconv.Itoa(math.MaxInt32))
_, err = node.Set("id", n)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
node, _ := NewSearcher(_TwitterJson).GetByPath("statuses", 3)
_, _ = node.Set("id", n)
}
}
func BenchmarkSetOne_Sjson(b *testing.B) {
path := fmt.Sprintf("%s.%d.%s", "statuses", 3, "id")
_, err := sjson.Set(_TwitterJson, path, math.MaxInt32)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
sjson.Set(_TwitterJson, path, math.MaxInt32)
}
}
func BenchmarkSetOne_Jsoniter(b *testing.B) {
data := []byte(_TwitterJson)
node, ok := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
if !ok {
b.Fatal(node)
}
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
node, _ := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
node["id"] = math.MaxInt32
}
}
func BenchmarkSetOne_Parallel_Sonic(b *testing.B) {
node, err := NewSearcher(_TwitterJson).GetByPath("statuses", 3)
if err != nil {
b.Fatal(err)
}
n := NewNumber(strconv.Itoa(math.MaxInt32))
_, err = node.Set("id", n)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
node, _ := NewSearcher(_TwitterJson).GetByPath("statuses", 3)
_, _ = node.Set("id", n)
}
})
}
func BenchmarkSetOne_Parallel_Sjson(b *testing.B) {
path := fmt.Sprintf("%s.%d.%s", "statuses", 3, "id")
_, err := sjson.Set(_TwitterJson, path, math.MaxInt32)
if err != nil {
b.Fatal(err)
}
b.SetBytes(int64(len(_TwitterJson)))
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
sjson.Set(_TwitterJson, path, math.MaxInt32)
}
})
}
func BenchmarkSetOne_Parallel_Jsoniter(b *testing.B) {
data := []byte(_TwitterJson)
node, ok := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
if !ok {
b.Fatal(node)
}
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
node, _ := jsoniter.Get(data, "statuses", 3).GetInterface().(map[string]interface{})
node["id"] = math.MaxInt32
}
})
}

BIN
bench-large.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

BIN
bench-small.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

View file

@ -10,11 +10,11 @@ cd $pwd/decoder
go test -benchmem -run=^$ -benchtime=100000x -bench "^(BenchmarkDecoder_Generic_Sonic|BenchmarkDecoder_Generic_StdLib|BenchmarkDecoder_Generic_JsonIter|BenchmarkDecoder_Generic_GoJson|BenchmarkDecoder_Binding_Sonic|BenchmarkDecoder_Binding_StdLib|BenchmarkDecoder_Binding_JsonIter|BenchmarkDecoder_Binding_GoJson|BenchmarkDecoder_Parallel_Generic_Sonic|BenchmarkDecoder_Parallel_Generic_StdLib|BenchmarkDecoder_Parallel_Generic_JsonIter|BenchmarkDecoder_Parallel_Generic_GoJson|BenchmarkDecoder_Parallel_Binding_Sonic|BenchmarkDecoder_Parallel_Binding_StdLib|BenchmarkDecoder_Parallel_Binding_JsonIter|BenchmarkDecoder_Parallel_Binding_GoJson)$"
cd $pwd/ast
go test -benchmem -run=^$ -benchtime=100000x -bench "^(BenchmarkSearchOne_Gjson|BenchmarkSearchOne_Jsoniter|BenchmarkSearchOne_Sonic|BenchmarkSearchOne_Parallel_Gjson|BenchmarkSearchOne_Parallel_Jsoniter|BenchmarkSearchOne_Parallel_Sonic)$"
go test -benchmem -run=^$ -benchtime=10000x -bench "^(BenchmarkParser_StdLib|BenchmarkParser_JsonIter|BenchmarkParser_Sonic|BenchmarkParser_Parallel_StdLib|BenchmarkParser_Parallel_JsonIter|BenchmarkParser_Parallel_Sonic|BenchmarkGetOne_Gjson|BenchmarkGetOne_Jsoniter|BenchmarkGetOne_Sonic|BenchmarkGetSeven_Gjson|BenchmarkGetSeven_Jsoniter|BenchmarkGetSeven_SonicParser)$"
go test -benchmem -run=^$ -benchtime=100000x -bench "^(BenchmarkGetOne_Sonic|BenchmarkGetOne_Gjson|BenchmarkGetOne_Jsoniter|BenchmarkGetOne_Parallel_Sonic|BenchmarkGetOne_Parallel_Gjson|BenchmarkGetOne_Parallel_Jsoniter|BenchmarkSetOne_Sonic|BenchmarkSetOne_Sjson|BenchmarkSetOne_Jsoniter|BenchmarkSetOne_Parallel_Sonic|BenchmarkSetOne_Parallel_Sjson|BenchmarkSetOne_Parallel_Jsoniter)$"
go test -benchmem -run=^$ -benchtime=10000x -bench "^(BenchmarkParser_Sonic|BenchmarkParser_Gjson|BenchmarkParser_JsonIter|BenchmarkParser_Parallel_Sonic|BenchmarkParser_Parallel_Gjson|BenchmarkParser_Parallel_StdLib|BenchmarkParser_Parallel_JsonIter|BenchmarkParseOne_Sonic|BenchmarkParseOne_Gjson|BenchmarkParseOne_Jsoniter|BenchmarkParseOne_Parallel_Sonic|BenchmarkParseOne_Parallel_Gjson|BenchmarkParseOne_Parallel_Jsoniter|BenchmarkParseSeven_Sonic|BenchmarkParseSeven_Gjson|BenchmarkParseSeven_Jsoniter|BenchmarkParseSeven_Parallel_Sonic|BenchmarkParseSeven_Parallel_Gjson|BenchmarkParseSeven_Parallel_Jsoniter)$"
go test -benchmem -run=^$ -benchtime=100000x -bench '^(BenchmarkEncodeRaw|BenchmarkEncodeSkip|BenchmarkEncodeLoad)$'
go test -benchmem -run=^$ -benchtime=10000000x -bench "^(BenchmarkNodeGetByPath|BenchmarkStructGetByPath_Jsoniter|BenchmarkNodeIndex|BenchmarkStructIndex|BenchmarkSliceIndex|BenchmarkMapIndex|BenchmarkNodeGet|BenchmarkSliceGet|BenchmarkMapGet|BenchmarkNodeSet|BenchmarkMapSet|BenchmarkNodeSetByIndex|BenchmarkSliceSetByIndex|BenchmarkStructSetByIndex|BenchmarkNodeUnset|BenchmarkMapUnset|BenchmarkNodUnsetByIndex|BenchmarkSliceUnsetByIndex|BenchmarkNodeAdd|BenchmarkSliceAdd|BenchmarkMapAdd)$"
go test -benchmem -run=^$ -benchtime=10000000x -bench "^(BenchmarkNodeGetByPath|BenchmarkStructGetByPath|BenchmarkNodeIndex|BenchmarkStructIndex|BenchmarkSliceIndex|BenchmarkMapIndex|BenchmarkNodeGet|BenchmarkSliceGet|BenchmarkMapGet|BenchmarkNodeSet|BenchmarkMapSet|BenchmarkNodeSetByIndex|BenchmarkSliceSetByIndex|BenchmarkStructSetByIndex|BenchmarkNodeUnset|BenchmarkMapUnset|BenchmarkNodUnsetByIndex|BenchmarkSliceUnsetByIndex|BenchmarkNodeAdd|BenchmarkSliceAdd|BenchmarkMapAdd)$"
unset SONIC_NO_ASYNC_GC
cd $pwd

View file

@ -122,8 +122,6 @@ func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {
func pretouchType(_vt reflect.Type, opts option.CompileOptions) (map[reflect.Type]bool, error) {
/* compile function */
compiler := newCompiler().apply(opts)
/* compile function */
decoder := func(vt *rt.GoType) (interface{}, error) {
if pp, err := compiler.compile(_vt); err != nil {
return nil, err

3
go.mod
View file

@ -9,6 +9,7 @@ require (
github.com/json-iterator/go v1.1.10
github.com/klauspost/cpuid/v2 v2.0.9
github.com/stretchr/testify v1.7.0
github.com/tidwall/gjson v1.8.0
github.com/tidwall/gjson v1.10.2
github.com/tidwall/sjson v1.2.3
github.com/twitchyliquid64/golang-asm v0.15.1
)

16
go.sum
View file

@ -1,4 +1,3 @@
github.com/chenzhuoyu/base64x v0.0.0-20210823082418-56861234f7ea/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 h1:1sDoSuDPWzhkdzNVxCxtIaKiAe96ESVPv8coGwc1gZ4=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -17,17 +16,18 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.3 h1:5+deguEhHSEjmuICXZ21uSSsXotWMA0orU783+Z7Cp8=
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=