mirror of
https://github.com/json-iterator/go.git
synced 2025-03-23 21:09:11 +02:00
optimize slice
This commit is contained in:
parent
87a35bd7e4
commit
71cdbd249c
@ -308,19 +308,46 @@ type sliceHeader struct {
|
||||
}
|
||||
|
||||
func (decoder *sliceDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
slice := (*sliceHeader)(ptr)
|
||||
slice.Len = 0
|
||||
for iter.ReadArray() {
|
||||
offset := uintptr(slice.Len) * decoder.elemType.Size()
|
||||
growOne(slice, decoder.sliceType, decoder.elemType)
|
||||
dataPtr := uintptr(slice.Data) + offset
|
||||
decoder.elemDecoder.decode(unsafe.Pointer(dataPtr), iter)
|
||||
}
|
||||
decoder.doDecode(ptr, iter)
|
||||
if iter.Error != nil && iter.Error != io.EOF {
|
||||
iter.Error = fmt.Errorf("%v: %s", decoder.sliceType, iter.Error.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (decoder *sliceDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
|
||||
slice := (*sliceHeader)(ptr)
|
||||
reuseSlice(slice, decoder.sliceType, 4)
|
||||
if !iter.ReadArray() {
|
||||
return
|
||||
}
|
||||
offset := uintptr(0)
|
||||
decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter)
|
||||
if !iter.ReadArray() {
|
||||
slice.Len = 1
|
||||
return
|
||||
}
|
||||
offset += decoder.elemType.Size()
|
||||
decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter)
|
||||
if !iter.ReadArray() {
|
||||
slice.Len = 2
|
||||
return
|
||||
}
|
||||
offset += decoder.elemType.Size()
|
||||
decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter)
|
||||
if !iter.ReadArray() {
|
||||
slice.Len = 3
|
||||
return
|
||||
}
|
||||
offset += decoder.elemType.Size()
|
||||
decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter)
|
||||
slice.Len = 4
|
||||
for iter.ReadArray() {
|
||||
growOne(slice, decoder.sliceType, decoder.elemType)
|
||||
offset += decoder.elemType.Size()
|
||||
decoder.elemDecoder.decode(unsafe.Pointer(uintptr(slice.Data) + offset), iter)
|
||||
}
|
||||
}
|
||||
|
||||
// grow grows the slice s so that it can hold extra more values, allocating
|
||||
// more capacity if needed. It also returns the old and new slice lengths.
|
||||
func growOne(slice *sliceHeader, sliceType reflect.Type, elementType reflect.Type) {
|
||||
@ -353,6 +380,15 @@ func growOne(slice *sliceHeader, sliceType reflect.Type, elementType reflect.Typ
|
||||
slice.Data = dst
|
||||
}
|
||||
|
||||
func reuseSlice(slice *sliceHeader, sliceType reflect.Type, expectedCap int) {
|
||||
if expectedCap <= slice.Cap {
|
||||
return
|
||||
}
|
||||
dst := unsafe.Pointer(reflect.MakeSlice(sliceType, 0, expectedCap).Pointer())
|
||||
slice.Cap = expectedCap
|
||||
slice.Data = dst
|
||||
}
|
||||
|
||||
var DECODERS unsafe.Pointer
|
||||
|
||||
func addDecoderToCache(cacheKey string, decoder Decoder) {
|
||||
|
@ -218,7 +218,7 @@ func Test_reflect_struct_tag_field(t *testing.T) {
|
||||
|
||||
func Test_reflect_slice(t *testing.T) {
|
||||
iter := ParseString(`["hello", "world"]`)
|
||||
slice := make([]string, 0, 1)
|
||||
slice := make([]string, 0, 5)
|
||||
iter.Read(&slice)
|
||||
if len(slice) != 2 {
|
||||
fmt.Println(iter.Error)
|
||||
@ -234,6 +234,24 @@ func Test_reflect_slice(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_reflect_large_slice(t *testing.T) {
|
||||
iter := ParseString(`[1,2,3,4,5,6,7,8,9]`)
|
||||
slice := make([]int, 0, 1)
|
||||
iter.Read(&slice)
|
||||
if len(slice) != 9 {
|
||||
fmt.Println(iter.Error)
|
||||
t.Fatal(len(slice))
|
||||
}
|
||||
if slice[0] != 1 {
|
||||
fmt.Println(iter.Error)
|
||||
t.Fatal(slice[0])
|
||||
}
|
||||
if slice[8] != 9 {
|
||||
fmt.Println(iter.Error)
|
||||
t.Fatal(slice[1])
|
||||
}
|
||||
}
|
||||
|
||||
func Test_reflect_nested(t *testing.T) {
|
||||
iter := ParseString(`[{"field1": "hello"}, null, {"field2": "world"}]`)
|
||||
slice := []*StructOfString{}
|
||||
@ -267,12 +285,12 @@ type StructOfTagOne struct {
|
||||
func Benchmark_jsoniter_reflect(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for n := 0; n < b.N; n++ {
|
||||
iter := ParseString(`{"field3": "100"}`)
|
||||
struct_ := StructOfTagOne{}
|
||||
iter.Read(&struct_)
|
||||
//iter := ParseString(`["hello", "world"]`)
|
||||
//array := make([]string, 0, 1)
|
||||
//iter.Read(&array)
|
||||
//iter := ParseString(`{"field3": "100"}`)
|
||||
//struct_ := StructOfTagOne{}
|
||||
//iter.Read(&struct_)
|
||||
iter := ParseString(`[1,2,3]`)
|
||||
var array []int
|
||||
iter.Read(&array)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user