From f4fca58809b4aa3b2d25bd52ae9d3ae21bc2fdd0 Mon Sep 17 00:00:00 2001 From: wdvxdr Date: Thu, 12 Aug 2021 20:43:19 +0800 Subject: [PATCH] feat(jce): optimize ReadSlice performance. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit name old time/op new time/op delta JceReader_ReadSlice-8 1.09ms ± 7% 0.52ms ± 1% -52.48% (p=0.000 n=10+10) name old speed new speed delta JceReader_ReadSlice-8 19.4MB/s ± 7% 40.8MB/s ± 1% +110.25% (p=0.000 n=10+10) name old alloc/op new alloc/op delta JceReader_ReadSlice-8 594kB ± 1% 266kB ± 0% -55.22% (p=0.000 n=9+9) name old allocs/op new allocs/op delta JceReader_ReadSlice-8 22.6k ± 0% 18.0k ± 0% -19.98% (p=0.000 n=10+10) --- binary/jce/reader.go | 22 ++++++++++++-------- binary/jce/reader_test.go | 43 +++++++++++++++++++++++++++++++++++++++ go.mod | 1 + 3 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 binary/jce/reader_test.go diff --git a/binary/jce/reader.go b/binary/jce/reader.go index 1f6efb88..d1609e06 100644 --- a/binary/jce/reader.go +++ b/binary/jce/reader.go @@ -380,26 +380,26 @@ func (r *JceReader) ReadSlice(i interface{}, tag int) { if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Slice { return } - if v.IsNil() { - return - } + t = t.Elem() if !r.skipToTag(tag) { return } hd, _ := r.readHead() if hd.Type == 9 { s := r.ReadInt32(0) + sv := reflect.MakeSlice(t, int(s), int(s)) + t = t.Elem() + val := reflect.New(t) for i := 0; i < int(s); i++ { - val := r.readObject(t.Elem(), 0) - v.Set(reflect.Append(v, val)) + r.ReadObject(val.Interface(), 0) + sv.Index(i).Set(val.Elem()) } + v.Set(sv) } - if hd.Type == 13 { + if hd.Type == 13 && t.Elem().Kind() == reflect.Uint8 { r.readHead() arr := r.readBytes(int(r.ReadInt32(0))) - for _, b := range arr { - v.Set(reflect.Append(v, reflect.ValueOf(b))) - } + v.SetBytes(arr) } } @@ -427,8 +427,12 @@ func (r *JceReader) ReadObject(i interface{}, tag int) { *o = r.ReadFloat64(tag) case *string: *o = r.ReadString(tag) + case *[]byte: + r.ReadSlice(o, tag) case IJceStruct: + r.readHead() o.ReadFrom(r) + r.skipToStructEnd() } } diff --git a/binary/jce/reader_test.go b/binary/jce/reader_test.go new file mode 100644 index 00000000..f3d2846a --- /dev/null +++ b/binary/jce/reader_test.go @@ -0,0 +1,43 @@ +package jce + +import ( + "math/rand" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestJceReader_ReadSlice(t *testing.T) { + s := make([]int64, 50) + for i := range s { + s[i] = rand.Int63() + } + w := NewJceWriter() + w.WriteObject(s, 1) + r := NewJceReader(w.Bytes()) + var result []int64 + r.ReadSlice(&result, 1) + assert.Equal(t, s, result) +} + +var test []*BigDataIPInfo + +func BenchmarkJceReader_ReadSlice(b *testing.B) { + for i := 0; i <= 500; i++ { + test = append(test, &BigDataIPInfo{ + Type: 1, + Server: "test1", + Port: 8080, + }) + } + w := NewJceWriter() + w.WriteObject(test, 1) + src := w.Bytes() + b.SetBytes(int64(len(src))) + b.StartTimer() + var result = []BigDataIPInfo{} + for i := 0; i < b.N; i++ { + r := NewJceReader(src) + r.ReadSlice(&result, 1) + } +} diff --git a/go.mod b/go.mod index f5b2f624..24ecc34e 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/json-iterator/go v1.1.10 github.com/modern-go/reflect2 v1.0.1 github.com/pkg/errors v0.9.1 + github.com/stretchr/testify v1.3.0 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c google.golang.org/protobuf v1.25.0 )