Repository: apache/dubbo-go-hessian2
Pull request #244 (2020-11-24 09:35:03)

rft: change value reference to ptr to improve performance
<!--  Thanks for sending a pull request! 
-->

**What this PR does**:
using reference type to improve performance

**Which issue(s) this PR fixes**:
NONE

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:

```release-note
- using reference type to improve performance
```


Patch:
diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml
index 70000d8..50480b8 100644
--- a/.github/workflows/github-actions.yml
+++ b/.github/workflows/github-actions.yml
@@ -5,8 +5,6 @@ on:
     branches: [ master ]
   pull_request:
     branches: "*"
-  pull_request_target:
-    branches: "*"
 
 jobs:
   build:
@@ -16,17 +14,15 @@ jobs:
 
     strategy:
       matrix:
-        os:
+        os: 
           - ubuntu-latest
         go_version:
-          - 1.13
+          - 1.12
         jdk_version:
           - 1.8
     env:
-      # DING_TOKEN: 049ae645b5dfb16e3240f81c1757333549ca46b30a5d6b40df562c63c36cf166
-      # DING_SIGN: SEC128fb97348610e9d4529bfb59ad7f3fd716b972785a0d04f1cee2c83ec160e59
-      DING_TOKEN: ${{ secrets.DING_TOKEN }}
-      DING_SIGN: ${{ secrets.DING_SIGN }}
+      DING_TOKEN: 049ae645b5dfb16e3240f81c1757333549ca46b30a5d6b40df562c63c36cf166
+      DING_SIGN: SEC128fb97348610e9d4529bfb59ad7f3fd716b972785a0d04f1cee2c83ec160e59
 
     steps:
     - uses: actions/checkout@v2
@@ -67,15 +63,13 @@ jobs:
         sh before_validate_license.sh
         chmod u+x /tmp/tools/license/license-header-checker
         /tmp/tools/license/license-header-checker -v -a -r -i vendor  /tmp/tools/license/license.txt . go  && [[ -z `git status -s` ]]
-
+    
     - name: Go Test
-      run: GO111MODULE=on && go mod vendor && go test -race -v && go test -bench . -race -coverprofile=coverage.txt
-
+      run: go mod vendor && go test -race -v && go test -bench . -race -coverprofile=coverage.txt
+      
     - name: Coverage
       run: bash <(curl -s https://codecov.io/bash)
 
-    - name: Hello world
-      run: echo Hello world ${{ secrets.DING_TOKEN }} ${{ secrets.DING_SIGN }}
 
       # Because the contexts of push and PR are different, there are two Notify.
       # Notifications are triggered only in the apache/dubbo-go-hessian2 repository.
@@ -83,7 +77,7 @@ jobs:
       uses: zcong1993/actions-ding@v3.0.1
       # Whether job is successful or not, always () is always true.
       if: |
-        always() &&
+        always() && 
         github.event_name == 'push' &&
         github.repository == 'apache/dubbo-go-hessian2'
       with:
@@ -99,11 +93,11 @@ jobs:
                 "text": "## Github Actions \n - name: CI \n - repository: ${{ github.repository }} \n - trigger: ${{ github.actor }} \n - event: ${{ github.event_name }} \n - ref: ${{ github.ref }} \n - status: [${{ job.status	}}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) \n - environment: ${{ runner.os }} \n > SHA: [${{ github.sha }}](${{ github.event.compare }})"
             }
           }
-
+          
     - name: DingTalk Message Notify only PR
       uses: zcong1993/actions-ding@v3.0.1
-      if: |
-        always() &&
+      if: | 
+        always() && 
         github.event_name == 'pull_request' &&
         github.repository == 'apache/dubbo-go-hessian2'
       with:
diff --git a/decode.go b/decode.go
index 35de60e..25ae24a 100644
--- a/decode.go
+++ b/decode.go
@@ -35,7 +35,7 @@ type Decoder struct {
 	// record type refs, both list and map need it
 	// todo: map
 	typeRefs      *TypeRefs
-	classInfoList []classInfo
+	classInfoList []*classInfo
 	isSkip        bool
 }
 
diff --git a/encode.go b/encode.go
index b0344d1..f20a476 100644
--- a/encode.go
+++ b/encode.go
@@ -33,7 +33,7 @@ import (
 
 // Encoder struct
 type Encoder struct {
-	classInfoList []classInfo
+	classInfoList []*classInfo
 	buffer        []byte
 	refMap        map[unsafe.Pointer]_refElem
 }
diff --git a/java_collection.go b/java_collection.go
index 5e66514..d669d12 100644
--- a/java_collection.go
+++ b/java_collection.go
@@ -88,7 +88,7 @@ func (JavaCollectionSerializer) EncObject(e *Encoder, vv POJO) error {
 	return nil
 }
 
-func (JavaCollectionSerializer) DecObject(d *Decoder, typ reflect.Type, cls classInfo) (interface{}, error) {
+func (JavaCollectionSerializer) DecObject(d *Decoder, typ reflect.Type, cls *classInfo) (interface{}, error) {
 	//for the java impl of hessian encode collections as list, which will not be decoded as object in go impl, this method should not be called
 	return nil, perrors.New("unexpected collection decode call")
 }
diff --git a/java_sql_time.go b/java_sql_time.go
index a359e8b..51e3abf 100644
--- a/java_sql_time.go
+++ b/java_sql_time.go
@@ -54,7 +54,7 @@ func (JavaSqlTimeSerializer) EncObject(e *Encoder, vv POJO) error {
 		i         int
 		idx       int
 		err       error
-		clsDef    classInfo
+		clsDef    *classInfo
 		className string
 		ptrV      reflect.Value
 	)
@@ -116,7 +116,7 @@ func (JavaSqlTimeSerializer) EncObject(e *Encoder, vv POJO) error {
 }
 
 // nolint
-func (JavaSqlTimeSerializer) DecObject(d *Decoder, typ reflect.Type, cls classInfo) (interface{}, error) {
+func (JavaSqlTimeSerializer) DecObject(d *Decoder, typ reflect.Type, cls *classInfo) (interface{}, error) {
 
 	if typ.Kind() != reflect.Struct {
 		return nil, perrors.Errorf("wrong type expect Struct but get:%s", typ.String())
diff --git a/java_unknown_exception.go b/java_unknown_exception.go
index 1b4196c..0663c4f 100644
--- a/java_unknown_exception.go
+++ b/java_unknown_exception.go
@@ -28,13 +28,13 @@ import (
 
 var exceptionCheckMutex sync.Mutex
 
-func checkAndGetException(cls classInfo) (structInfo, bool) {
+func checkAndGetException(cls *classInfo) (*structInfo, bool) {
 
 	if len(cls.fieldNameList) < 4 {
-		return structInfo{}, false
+		return nil, false
 	}
 	var (
-		throwable structInfo
+		throwable *structInfo
 		ok        bool
 	)
 	var count = 0
diff --git a/list.go b/list.go
index d8ed019..8c70310 100644
--- a/list.go
+++ b/list.go
@@ -114,10 +114,11 @@ func getListType(javalistname string) reflect.Type {
 
 	if sliceTy == nil {
 		tpStructInfo, _ := getStructInfo(javaname)
-		tp := tpStructInfo.typ
-		if tp == nil {
+		if tpStructInfo == nil || tpStructInfo.typ == nil {
 			return nil
 		}
+
+		tp := tpStructInfo.typ
 		if tp.Kind() != reflect.Ptr {
 			tp = reflect.New(tp).Type()
 		}
diff --git a/object.go b/object.go
index bec2de4..b398f25 100644
--- a/object.go
+++ b/object.go
@@ -104,7 +104,7 @@ func (e *Encoder) encObject(v POJO) error {
 		idx    int
 		num    int
 		err    error
-		clsDef classInfo
+		clsDef *classInfo
 	)
 
 	vv := reflect.ValueOf(v)
@@ -292,7 +292,7 @@ func (d *Decoder) decClassDef() (interface{}, error) {
 		fieldList[i] = fieldName
 	}
 
-	return classInfo{javaName: clsName, fieldNameList: fieldList}, nil
+	return &classInfo{javaName: clsName, fieldNameList: fieldList}, nil
 }
 
 type fieldInfo struct {
@@ -362,7 +362,7 @@ func findField(name string, typ reflect.Type) ([]int, *reflect.StructField, erro
 	return []int{}, nil, perrors.Errorf("failed to find field %s", name)
 }
 
-func (d *Decoder) decInstance(typ reflect.Type, cls classInfo) (interface{}, error) {
+func (d *Decoder) decInstance(typ reflect.Type, cls *classInfo) (interface{}, error) {
 	if typ.Kind() != reflect.Struct {
 		return nil, perrors.Errorf("wrong type expect Struct but get:%s", typ.String())
 	}
@@ -537,15 +537,15 @@ func (d *Decoder) decInstance(typ reflect.Type, cls classInfo) (interface{}, err
 	return vRef.Interface(), nil
 }
 
-func (d *Decoder) appendClsDef(cd classInfo) {
+func (d *Decoder) appendClsDef(cd *classInfo) {
 	d.classInfoList = append(d.classInfoList, cd)
 }
 
-func (d *Decoder) getStructDefByIndex(idx int) (reflect.Type, classInfo, error) {
+func (d *Decoder) getStructDefByIndex(idx int) (reflect.Type, *classInfo, error) {
 	var (
 		ok  bool
-		cls classInfo
-		s   structInfo
+		cls *classInfo
+		s   *structInfo
 		err error
 	)
 
@@ -573,7 +573,7 @@ func (d *Decoder) decEnum(javaName string, flag int32) (JavaEnum, error) {
 		err       error
 		enumName  string
 		ok        bool
-		info      structInfo
+		info      *structInfo
 		enumValue JavaEnum
 	)
 	enumName, err = d.decString(TAG_READ) // java enum class member is "name"
@@ -591,7 +591,7 @@ func (d *Decoder) decEnum(javaName string, flag int32) (JavaEnum, error) {
 }
 
 // skip this object
-func (d *Decoder) skip(cls classInfo) error {
+func (d *Decoder) skip(cls *classInfo) error {
 	len := len(cls.fieldNameList)
 	if len < 1 {
 		return nil
@@ -613,7 +613,7 @@ func (d *Decoder) decObject(flag int32) (interface{}, error) {
 		idx int32
 		err error
 		typ reflect.Type
-		cls classInfo
+		cls *classInfo
 	)
 
 	if flag != TAG_READ {
@@ -632,7 +632,7 @@ func (d *Decoder) decObject(flag int32) (interface{}, error) {
 		if err != nil {
 			return nil, perrors.Wrap(err, "decObject->decClassDef byte double")
 		}
-		cls, _ = clsDef.(classInfo)
+		cls, _ = clsDef.(*classInfo)
 		//add to slice
 		d.appendClsDef(cls)
 
diff --git a/pojo.go b/pojo.go
index 8ed2e42..272037e 100644
--- a/pojo.go
+++ b/pojo.go
@@ -89,15 +89,15 @@ type structInfo struct {
 // POJORegistry pojo registry struct
 type POJORegistry struct {
 	sync.RWMutex
-	classInfoList []classInfo           // {class name, field name list...} list
-	j2g           map[string]string     // java class name --> go struct name
-	registry      map[string]structInfo // go class name --> go struct info
+	classInfoList []*classInfo           // {class name, field name list...} list
+	j2g           map[string]string      // java class name --> go struct name
+	registry      map[string]*structInfo // go class name --> go struct info
 }
 
 var (
-	pojoRegistry = POJORegistry{
+	pojoRegistry = &POJORegistry{
 		j2g:      make(map[string]string),
-		registry: make(map[string]structInfo),
+		registry: make(map[string]*structInfo),
 	}
 	pojoType     = reflect.TypeOf((*POJO)(nil)).Elem()
 	javaEnumType = reflect.TypeOf((*POJOEnum)(nil)).Elem()
@@ -205,8 +205,8 @@ func RegisterPOJOMapping(javaClassName string, o interface{}) int {
 	clsDef.buffer = append(bHeader, bBody...)
 
 	structInfo.index = len(pojoRegistry.classInfoList)
-	pojoRegistry.classInfoList = append(pojoRegistry.classInfoList, clsDef)
-	pojoRegistry.registry[structInfo.goName] = structInfo
+	pojoRegistry.classInfoList = append(pojoRegistry.classInfoList, &clsDef)
+	pojoRegistry.registry[structInfo.goName] = &structInfo
 
 	return structInfo.index
 }
@@ -307,8 +307,8 @@ func RegisterJavaEnum(o POJOEnum) int {
 		c = classInfo{javaName: t.javaName, fieldNameList: l}
 		c.buffer = append(c.buffer, b[:]...)
 		t.index = len(pojoRegistry.classInfoList)
-		pojoRegistry.classInfoList = append(pojoRegistry.classInfoList, c)
-		pojoRegistry.registry[t.goName] = t
+		pojoRegistry.classInfoList = append(pojoRegistry.classInfoList, &c)
+		pojoRegistry.registry[t.goName] = &t
 		i = t.index
 	} else {
 		i = -1
@@ -319,23 +319,32 @@ func RegisterJavaEnum(o POJOEnum) int {
 
 // check if go struct name @goName has been registered or not.
 func checkPOJORegistry(goName string) (int, bool) {
+	s, ok := loadPOJORegistry(goName)
+	if !ok {
+		return -1, false
+	}
+	return s.index, true
+}
+
+// load struct info if go struct name @goName has been registered or not.
+func loadPOJORegistry(goName string) (*structInfo, bool) {
 	var (
 		ok bool
-		s  structInfo
+		s  *structInfo
 	)
 	pojoRegistry.RLock()
 	s, ok = pojoRegistry.registry[goName]
 	pojoRegistry.RUnlock()
 
-	return s.index, ok
+	return s, ok
 }
 
 // @typeName is class's java name
-func getStructInfo(javaName string) (structInfo, bool) {
+func getStructInfo(javaName string) (*structInfo, bool) {
 	var (
 		ok bool
 		g  string
-		s  structInfo
+		s  *structInfo
 	)
 
 	pojoRegistry.RLock()
@@ -348,12 +357,12 @@ func getStructInfo(javaName string) (structInfo, bool) {
 	return s, ok
 }
 
-func getStructDefByIndex(idx int) (reflect.Type, classInfo, error) {
+func getStructDefByIndex(idx int) (reflect.Type, *classInfo, error) {
 	var (
 		ok      bool
 		clsName string
-		cls     classInfo
-		s       structInfo
+		cls     *classInfo
+		s       *structInfo
 	)
 
 	pojoRegistry.RLock()
@@ -380,7 +389,7 @@ func getStructDefByIndex(idx int) (reflect.Type, classInfo, error) {
 func createInstance(goName string) interface{} {
 	var (
 		ok bool
-		s  structInfo
+		s  *structInfo
 	)
 
 	pojoRegistry.RLock()
diff --git a/serialize.go b/serialize.go
index 2584d10..b57702b 100644
--- a/serialize.go
+++ b/serialize.go
@@ -37,7 +37,7 @@ func init() {
 
 type Serializer interface {
 	EncObject(*Encoder, POJO) error
-	DecObject(*Decoder, reflect.Type, classInfo) (interface{}, error)
+	DecObject(*Decoder, reflect.Type, *classInfo) (interface{}, error)
 }
 
 var serializerMap = make(map[string]Serializer, 16)
@@ -53,7 +53,7 @@ func GetSerializer(javaClassName string) (Serializer, bool) {
 
 type IntegerSerializer struct{}
 
-func (IntegerSerializer) DecObject(d *Decoder, typ reflect.Type, cls classInfo) (interface{}, error) {
+func (IntegerSerializer) DecObject(d *Decoder, typ reflect.Type, cls *classInfo) (interface{}, error) {
 	bigInt, err := d.decInstance(typ, cls)
 	if err != nil {
 		return nil, err
@@ -88,7 +88,7 @@ func (DecimalSerializer) EncObject(e *Encoder, v POJO) error {
 	return e.encObject(decimal)
 }
 
-func (DecimalSerializer) DecObject(d *Decoder, typ reflect.Type, cls classInfo) (interface{}, error) {
+func (DecimalSerializer) DecObject(d *Decoder, typ reflect.Type, cls *classInfo) (interface{}, error) {
 	dec, err := d.decInstance(typ, cls)
 	if err != nil {
 		return nil, err


Test patch:
diff --git a/java_unknown_exception_test.go b/java_unknown_exception_test.go
index ea24321..20c8e6c 100644
--- a/java_unknown_exception_test.go
+++ b/java_unknown_exception_test.go
@@ -25,7 +25,7 @@ import (
 )
 
 func TestCheckAndGetException(t *testing.T) {
-	clazzInfo1 := classInfo{
+	clazzInfo1 := &classInfo{
 		javaName:      "com.test.UserDefinedException",
 		fieldNameList: []string{"detailMessage", "code", "suppressedExceptions", "stackTrace", "cause"},
 	}
@@ -35,11 +35,11 @@ func TestCheckAndGetException(t *testing.T) {
 	assert.Equal(t, s.javaName, "com.test.UserDefinedException")
 	assert.Equal(t, s.goName, "hessian.UnknownException")
 
-	clazzInfo2 := classInfo{
+	clazzInfo2 := &classInfo{
 		javaName:      "com.test.UserDefinedException",
 		fieldNameList: []string{"detailMessage", "code", "suppressedExceptions", "cause"},
 	}
 	s, b = checkAndGetException(clazzInfo2)
 	assert.False(t, b)
-	assert.Equal(t, s, structInfo{})
+	assert.Nil(t, s)
 }
diff --git a/object_test.go b/object_test.go
index 1bdeafa..7e59157 100644
--- a/object_test.go
+++ b/object_test.go
@@ -564,9 +564,9 @@ func doTestBasePointer(t *testing.T, base *BasePointer, expected *BasePointer) {
 
 func TestSkip(t *testing.T) {
 	// clear pojo
-	pojoRegistry = POJORegistry{
+	pojoRegistry = &POJORegistry{
 		j2g:      make(map[string]string),
-		registry: make(map[string]structInfo),
+		registry: make(map[string]*structInfo),
 	}
 	testDecodeFrameworkWithSkip(t, "replyObject_0", nil)
 	testDecodeFrameworkWithSkip(t, "replyObject_1", nil)