https://github.com/json-iterator/go
仍然使用反射实现,但是比 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 则报错。
如果使用更底层的 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
1
spider82 2016-12-05 00:53:39 +08:00
mark
|
2
scnace 2016-12-05 01:15:13 +08:00 via Android
mark 一发起床看
|
3
myself659410 2016-12-05 09:44:33 +08:00
https://github.com/pquerna/ffjson 也是 encoding/json 的 2 倍到 3 倍
|
4
taowen OP @myself659410 ffjson 需要 go generate 静态生成代码,而 jsoniter 的性能数字是在同样使用反射的前提下测得的。另外 ffjson 不支持用 io.Reader 做为输入,需要把所有的 json 读入为 []byte 再处理。
|
5
lwhile521 2016-12-05 10:16:04 +08:00
已给 star~
|
6
ggaaooppeenngg 2016-12-05 10:57:24 +08:00
用 reflect.TypeOf 确定一个 json 的 schema => 这个能认出 omitempty 这样的 tag 么?
112 B/op 内存分配貌似降下来了, 为什么避开反射时间增加了? |
7
taowen OP @ggaaooppeenngg 支持了 -, string 这些 tag ,没有支持 omitempty 。
``` type StructOfTag struct { field1 string `json:"field-1"` field2 string `json:"-"` field3 int `json:",string"` } func Test_reflect_struct_tag_field(t *testing.T) { err := jsoniter.Unmarshal(`{"field-1": "hello", "field2": "", "field3": "100"}`, &struct_) if struct_.field1 != "hello" { fmt.Println(err) t.Fatal(struct_.field1) } if struct_.field2 != "world" { fmt.Println(err) t.Fatal(struct_.field2) } if struct_.field3 != 100 { fmt.Println(err) t.Fatal(struct_.field3) } } ``` 不走反射速度是最快的啊 455 ns/op ,是标准库的 1/5 |
8
ggaaooppeenngg 2016-12-05 17:51:12 +08:00 via iPhone
|
9
nomoon 2016-12-07 02:15:55 +08:00
|