From d393a3228d4a785cc5662a2fb4381e9259c74b18 Mon Sep 17 00:00:00 2001 From: liu Date: Fri, 19 May 2023 16:52:16 +0800 Subject: [PATCH] doc: chore readme (#420) --- README.md | 23 +++++++++--------- INTRODUCTION.md => docs/INTRODUCTION.md | 4 +-- bench-large.png => docs/imgs/bench-large.png | Bin bench-small.png => docs/imgs/bench-small.png | Bin .../imgs/introduction-1.png | Bin .../imgs/introduction-2.png | Bin other-langs.png => docs/imgs/other-langs.png | Bin 7 files changed, 14 insertions(+), 13 deletions(-) rename INTRODUCTION.md => docs/INTRODUCTION.md (98%) rename bench-large.png => docs/imgs/bench-large.png (100%) rename bench-small.png => docs/imgs/bench-small.png (100%) rename introduction-1.png => docs/imgs/introduction-1.png (100%) rename introduction-2.png => docs/imgs/introduction-2.png (100%) rename other-langs.png => docs/imgs/other-langs.png (100%) diff --git a/README.md b/README.md index 9cc42c4..dd40434 100644 --- a/README.md +++ b/README.md @@ -76,14 +76,14 @@ BenchmarkSetOne_Parallel_Sjson-16 18194 ns/op 715.7 BenchmarkSetOne_Parallel_Jsoniter-16 33560 ns/op 388.05 MB/s 45892 B/op 964 allocs/op ``` - [Small](https://github.com/bytedance/sonic/blob/main/testdata/small.go) (400B, 11 keys, 3 layers) -![small benchmarks](bench-small.png) +![small benchmarks](./docs/imgs/bench-small.png) - [Large](https://github.com/bytedance/sonic/blob/main/testdata/twitter.json) (635KB, 10000+ key, 6 layers) -![large benchmarks](bench-large.png) +![large benchmarks](./docs/imgs/bench-large.png) See [bench.sh](https://github.com/bytedance/sonic/blob/main/bench.sh) for benchmark codes. ## How it works -See [INTRODUCTION.md](INTRODUCTION.md). +See [INTRODUCTION.md](./docs/INTRODUCTION.md). ## Usage @@ -104,28 +104,29 @@ err := sonic.Unmarshal(output, &data) Sonic supports decoding json from `io.Reader` or encoding objects into `io.`Writer`, aims at handling multiple values as well as reducing memory consumption. - encoder ```go -import "github.com/bytedance/sonic/encoder" - var o1 = map[string]interface{}{ "a": "b", } var o2 = 1 var w = bytes.NewBuffer(nil) -var enc = encoder.NewStreamEncoder(w) +var enc = sonic.ConfigDefault.NewEncoder(w) enc.Encode(o1) enc.Encode(o2) -println(w.String()) // "{"a":"b"}\n1" +fmt.Println(w.String()) +// Output: +// {"a":"b"} +// 1 ``` - decoder ```go -import "github.com/bytedance/sonic/decoder" - var o = map[string]interface{}{} var r = strings.NewReader(`{"a":"b"}{"1":"2"}`) -var dec = decoder.NewStreamDecoder(r) +var dec = sonic.ConfigDefault.NewDecoder(r) dec.Decode(&o) dec.Decode(&o) -fmt.Printf("%+v", o) // map[1:2 a:b] +fmt.Printf("%+v", o) +// Output: +// map[1:2 a:b] ``` ### Use Number/Use Int64 diff --git a/INTRODUCTION.md b/docs/INTRODUCTION.md similarity index 98% rename from INTRODUCTION.md rename to docs/INTRODUCTION.md index 6b42118..44cd1da 100644 --- a/INTRODUCTION.md +++ b/docs/INTRODUCTION.md @@ -12,7 +12,7 @@ Before starting our design, we need to figure out some questions: ### Why is Json-iterator faster than Standard Library? First of all, the **schema-based processing mechanism** used by the standard library is commendable, in which the parser can obtain meta information in advance when scanning, thereby shortening the time of branch selection. However, its original implementation did not make good use of this mechanism, instead, **it spent a lot of time reflecting to obtain meta info of schema**. Meanwhile, The approach of json-iterator is: Interprete structure as field-by-field encoding and decoding functions, and then assembled and cached them, minimizing the performance loss cost by reflection. But does it work once and for all? No. In practical tests, we found that **the deeper and larger the input JSON got, the smaller the gap between json-iterator and other libraries gradually became** - eventually event got surpassed: -![Scalability](introduction-1.png) +![Scalability](./imgs/introduction-1.png) The reason is that **this implementation transforms into a large number of interface encapsulations and function calls**, followed by function-call losses: 1. **Calling interface involves dynamic addressing of itab** @@ -39,7 +39,7 @@ Based on the above questions, our design is easy to implement: 2. For practical scenarios where big data and small data coexist, we **use pre-conditional judgment** (string size, floating precision, etc.) **to combine `SIMD` with scalar instructions** to achieve the best adaptation. 3. As for insufficiency in compiling optimization of go language, we decided to **use `C/Clang` to write and compile core computational functions**, and **developed a set of [asm2asm](https://github.com/chenzhuoyu/asm2asm) tools to translate the fully optimized x86 assembly into plan9** and finally load it into Golang runtime. 4. Giving the big speed gap between parsing and skipping, the **`lazy-load` mechanism** is certainly used in our AST parser, but in **a more adaptive and efficient way to reduce the overhead of multiple-key queries**. -![design](introduction-2.png) +![design](./imgs/introduction-2.png) In detail, we conducted some further optimization: 1. Since the native-asm functions cannot be inlined in Golang, we found that its cost even exceeded the improvement brought by the optimization of the C compiler. So we reimplemented a set of lightweight function-calls in JIT: diff --git a/bench-large.png b/docs/imgs/bench-large.png similarity index 100% rename from bench-large.png rename to docs/imgs/bench-large.png diff --git a/bench-small.png b/docs/imgs/bench-small.png similarity index 100% rename from bench-small.png rename to docs/imgs/bench-small.png diff --git a/introduction-1.png b/docs/imgs/introduction-1.png similarity index 100% rename from introduction-1.png rename to docs/imgs/introduction-1.png diff --git a/introduction-2.png b/docs/imgs/introduction-2.png similarity index 100% rename from introduction-2.png rename to docs/imgs/introduction-2.png diff --git a/other-langs.png b/docs/imgs/other-langs.png similarity index 100% rename from other-langs.png rename to docs/imgs/other-langs.png