比 encoding/json 更快地解析 json

taowen發表於2016-12-04

https://github.com/json-iterator/go

直接替換 json.Unmarshal

仍然使用反射實現,但是比 encoding/json 的版本更快。完整的測試程式碼:https://github.com/json-iterator/go-benchmark

func Benchmark_array_by_stardard_lib(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        sample := make([]int, 0, 10)
        json.Unmarshal([]byte(`[1,2,3,4,5,6,7,8,9]`), &sample)
    }
}

500000 2478 ns/op 408 B/op 14 allocs/op

func Benchmark_array_by_jsoniter(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        sample := make([]int, 0, 10)
        jsoniter.Unmarshal([]byte(`[1,2,3,4,5,6,7,8,9]`), &sample)
    }
}

2000000 740 ns/op 224 B/op 4 allocs/op

和 encoding/json 的區別是,標準庫使用的是 reflect.ValueOf,然後根據 json 的輸入情況去找對應的 field 和 element。而 jsoniter 的實現是反過來的,用 reflect.TypeOf 確定一個 json 的 schema,然後根據 schema 產生對應的 decoder。如果 json 輸入不符合這個 decoder 則報錯。

StAX 風格的 API

如果使用更底層的 api,可以完全避免反射的開銷

func Benchmark_array_by_jsoniter_direct(b *testing.B) {
    b.ReportAllocs()
    for n := 0; n < b.N; n++ {
        sample := make([]uint64, 0, 10)
        iter := jsoniter.ParseString(`[1,2,3,4,5,6,7,8,9]`)
        for iter.ReadArray() {
            sample = append(sample, iter.ReadUint64())
        }
    }
}

3000000 455 ns/op 112 B/op 2 allocs/op

更多原創文章乾貨分享,請關注公眾號
  • 比 encoding/json 更快地解析 json
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章