From 2ad2f11326680522a8cab68c7703912c4d5e5937 Mon Sep 17 00:00:00 2001 From: IncSW Date: Fri, 30 Apr 2021 19:09:15 +0300 Subject: [PATCH 1/3] when cap is enough, reuse slice data for compatibility with encoding/json --- decode_slice.go | 36 ++++++++++++++++++++---------------- decode_test.go | 10 ++++++++-- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/decode_slice.go b/decode_slice.go index ea09f88..a80307e 100644 --- a/decode_slice.go +++ b/decode_slice.go @@ -96,10 +96,11 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er s.cursor++ s.skipWhiteSpace() if s.char() == ']' { - *(*sliceHeader)(p) = sliceHeader{ - data: newArray(d.elemType, 0), - len: 0, - cap: 0, + dst := (*sliceHeader)(p) + if dst.data == nil { + dst.data = newArray(d.elemType, 0) + } else { + dst.len = 0 } s.cursor++ return nil @@ -130,11 +131,12 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er slice.cap = capacity slice.len = idx + 1 slice.data = data + dst := *(*sliceHeader)(p) + dst.len = idx + 1 dstCap := idx + 1 - dst := sliceHeader{ - data: newArray(d.elemType, dstCap), - len: idx + 1, - cap: dstCap, + if dstCap > dst.cap { + dst.data = newArray(d.elemType, dstCap) + dst.cap = dstCap } copySlice(d.elemType, dst, sliceHeader{ data: slice.data, @@ -210,10 +212,11 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) cursor++ cursor = skipWhiteSpace(buf, cursor) if buf[cursor] == ']' { - **(**sliceHeader)(unsafe.Pointer(&p)) = sliceHeader{ - data: newArray(d.elemType, 0), - len: 0, - cap: 0, + dst := (*sliceHeader)(p) + if dst.data == nil { + dst.data = newArray(d.elemType, 0) + } else { + dst.len = 0 } cursor++ return cursor, nil @@ -245,11 +248,12 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) slice.cap = capacity slice.len = idx + 1 slice.data = data + dst := *(*sliceHeader)(p) + dst.len = idx + 1 dstCap := idx + 1 - dst := sliceHeader{ - data: newArray(d.elemType, dstCap), - len: idx + 1, - cap: dstCap, + if dstCap > dst.cap { + dst.data = newArray(d.elemType, dstCap) + dst.cap = dstCap } copySlice(d.elemType, dst, sliceHeader{ data: slice.data, diff --git a/decode_test.go b/decode_test.go index 574341f..2eb01d9 100644 --- a/decode_test.go +++ b/decode_test.go @@ -103,6 +103,12 @@ func Test_Decoder(t *testing.T) { assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v)) assertEq(t, "slice", fmt.Sprint([]int{1, 2, 3, 4}), fmt.Sprint(v)) }) + t.Run("slice_reuse_data", func(t *testing.T) { + v := make([]int, 0, 10) + assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v)) + assertEq(t, "slice", fmt.Sprint([]int{1, 2, 3, 4}), fmt.Sprint(v)) + assertEq(t, "cap", 10, cap(v)) + }) t.Run("array", func(t *testing.T) { var v [4]int assertErr(t, json.Unmarshal([]byte(` [ 1 , 2 , 3 , 4 ] `), &v)) @@ -121,10 +127,10 @@ func Test_Decoder(t *testing.T) { { "a": { "nestedA": "value of nested a" - }, + }, "b": { "nestedB": "value of nested b" - }, + }, "c": { "nestedC": "value of nested c" } From e6ff77fe8d83d2551eb803a115fbacc5b08af29d Mon Sep 17 00:00:00 2001 From: IncSW Date: Fri, 30 Apr 2021 20:07:44 +0300 Subject: [PATCH 2/3] remove useless dstCap var --- decode_slice.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/decode_slice.go b/decode_slice.go index a80307e..c85482b 100644 --- a/decode_slice.go +++ b/decode_slice.go @@ -133,10 +133,9 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er slice.data = data dst := *(*sliceHeader)(p) dst.len = idx + 1 - dstCap := idx + 1 - if dstCap > dst.cap { - dst.data = newArray(d.elemType, dstCap) - dst.cap = dstCap + if dst.len > dst.cap { + dst.data = newArray(d.elemType, dst.len) + dst.cap = dst.len } copySlice(d.elemType, dst, sliceHeader{ data: slice.data, @@ -250,10 +249,9 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) slice.data = data dst := *(*sliceHeader)(p) dst.len = idx + 1 - dstCap := idx + 1 - if dstCap > dst.cap { - dst.data = newArray(d.elemType, dstCap) - dst.cap = dstCap + if dst.len > dst.cap { + dst.data = newArray(d.elemType, dst.len) + dst.cap = dst.len } copySlice(d.elemType, dst, sliceHeader{ data: slice.data, From c7747ba9b2caf9da610181fa000376f140b94152 Mon Sep 17 00:00:00 2001 From: IncSW Date: Mon, 3 May 2021 10:55:17 +0300 Subject: [PATCH 3/3] remove unnecessary assignments --- decode_slice.go | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/decode_slice.go b/decode_slice.go index c85482b..0198ab0 100644 --- a/decode_slice.go +++ b/decode_slice.go @@ -131,18 +131,13 @@ func (d *sliceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) er slice.cap = capacity slice.len = idx + 1 slice.data = data - dst := *(*sliceHeader)(p) + dst := (*sliceHeader)(p) dst.len = idx + 1 if dst.len > dst.cap { dst.data = newArray(d.elemType, dst.len) dst.cap = dst.len } - copySlice(d.elemType, dst, sliceHeader{ - data: slice.data, - len: slice.len, - cap: slice.cap, - }) - *(*sliceHeader)(p) = dst + copySlice(d.elemType, *dst, *slice) d.releaseSlice(slice) s.cursor++ return nil @@ -247,18 +242,13 @@ func (d *sliceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) slice.cap = capacity slice.len = idx + 1 slice.data = data - dst := *(*sliceHeader)(p) + dst := (*sliceHeader)(p) dst.len = idx + 1 if dst.len > dst.cap { dst.data = newArray(d.elemType, dst.len) dst.cap = dst.len } - copySlice(d.elemType, dst, sliceHeader{ - data: slice.data, - len: slice.len, - cap: slice.cap, - }) - **(**sliceHeader)(unsafe.Pointer(&p)) = dst + copySlice(d.elemType, *dst, *slice) d.releaseSlice(slice) cursor++ return cursor, nil