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