mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 11:18:02 +08:00
improve performance for gconv.Struct
This commit is contained in:
parent
1edc1f35fb
commit
e1dd5cce7d
@ -24,6 +24,7 @@ func TagFields(pointer interface{}, priority []string) []*Field {
|
||||
// doTagFields retrieves the tag and corresponding attribute name from <pointer>. It also filters repeated
|
||||
// tag internally.
|
||||
// The parameter <pointer> should be type of struct/*struct.
|
||||
// TODO remove third-party package "structs" by reducing the reflect usage to improve the performance.
|
||||
func doTagFields(pointer interface{}, priority []string, tagMap map[string]struct{}) []*Field {
|
||||
// If <pointer> points to an invalid address, for example a nil variable,
|
||||
// it here creates an empty struct using reflect feature.
|
||||
|
@ -7,16 +7,10 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"bytes"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// replaceCharReg is the regular expression object for replacing chars in key.
|
||||
// It is used for function EqualFoldWithoutChars.
|
||||
replaceCharReg, _ = regexp.Compile(`[\-\.\_\s]+`)
|
||||
)
|
||||
|
||||
// IsLetterUpper checks whether the given byte b is in upper case.
|
||||
func IsLetterUpper(b byte) bool {
|
||||
if b >= byte('A') && b <= byte('Z') {
|
||||
@ -83,11 +77,19 @@ func ReplaceByMap(origin string, replaces map[string]string) string {
|
||||
return origin
|
||||
}
|
||||
|
||||
// RemoveSymbols removes all symbols from string and lefts only numbers and letters.
|
||||
func RemoveSymbols(s string) string {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
for _, c := range s {
|
||||
if (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') {
|
||||
buffer.WriteByte(byte(c))
|
||||
}
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// EqualFoldWithoutChars checks string <s1> and <s2> equal case-insensitively,
|
||||
// with/without chars '-'/'_'/'.'/' '.
|
||||
func EqualFoldWithoutChars(s1, s2 string) bool {
|
||||
return strings.EqualFold(
|
||||
replaceCharReg.ReplaceAllString(s1, ""),
|
||||
replaceCharReg.ReplaceAllString(s2, ""),
|
||||
)
|
||||
return strings.EqualFold(RemoveSymbols(s1), RemoveSymbols(s2))
|
||||
}
|
||||
|
29
internal/utils/utils_z_bench_test.go
Normal file
29
internal/utils/utils_z_bench_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2020 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/internal/utils"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
replaceCharReg, _ = regexp.Compile(`[\-\.\_\s]+`)
|
||||
)
|
||||
|
||||
func Benchmark_RemoveSymbols(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
utils.RemoveSymbols(`-a-b._a c1!@#$%^&*()_+:";'.,'01`)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_RegularReplaceChars(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
replaceCharReg.ReplaceAllString(`-a-b._a c1!@#$%^&*()_+:";'.,'01`, "")
|
||||
}
|
||||
}
|
@ -63,3 +63,9 @@ func Test_ReadCloser(t *testing.T) {
|
||||
t.Assert(r, []byte{1, 2, 3, 4})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_RemoveSymbols(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(utils.RemoveSymbols(`-a-b._a c1!@#$%^&*()_+:";'.,'01`), `abac101`)
|
||||
})
|
||||
}
|
||||
|
@ -12,19 +12,12 @@ import (
|
||||
"github.com/gogf/gf/internal/empty"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/internal/structs"
|
||||
"github.com/gogf/gf/internal/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
// replaceCharReg is the regular expression object for replacing chars
|
||||
// in map keys and attribute names.
|
||||
replaceCharReg, _ = regexp.Compile(`[\-\.\_\s]+`)
|
||||
)
|
||||
|
||||
// Struct maps the params key-value pairs to the corresponding struct object's attributes.
|
||||
// The third parameter <mapping> is unnecessary, indicating the mapping rules between the
|
||||
// custom key name and the attribute name(case sensitive).
|
||||
@ -193,7 +186,7 @@ func doStruct(params interface{}, pointer interface{}, mapping ...map[string]str
|
||||
}
|
||||
} else {
|
||||
tempName = elemFieldType.Name
|
||||
attrMap[tempName] = replaceCharReg.ReplaceAllString(tempName, "")
|
||||
attrMap[tempName] = utils.RemoveSymbols(tempName)
|
||||
}
|
||||
}
|
||||
if len(attrMap) == 0 {
|
||||
@ -204,7 +197,7 @@ func doStruct(params interface{}, pointer interface{}, mapping ...map[string]str
|
||||
// and the value is its replaced tag name for later comparison to improve performance.
|
||||
tagMap := make(map[string]string)
|
||||
for k, v := range structs.TagMapName(pointer, StructTagPriority) {
|
||||
tagMap[v] = replaceCharReg.ReplaceAllString(k, "")
|
||||
tagMap[v] = utils.RemoveSymbols(k)
|
||||
}
|
||||
|
||||
var (
|
||||
@ -213,7 +206,7 @@ func doStruct(params interface{}, pointer interface{}, mapping ...map[string]str
|
||||
)
|
||||
for mapK, mapV := range paramsMap {
|
||||
attrName = ""
|
||||
checkName = replaceCharReg.ReplaceAllString(mapK, "")
|
||||
checkName = utils.RemoveSymbols(mapK)
|
||||
// Loop to find the matched attribute name with or without
|
||||
// string cases and chars like '-'/'_'/'.'/' '.
|
||||
|
||||
|
32
util/gconv/gconv_z_bench_struct_test.go
Normal file
32
util/gconv/gconv_z_bench_struct_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type structType struct {
|
||||
Name string
|
||||
Score int
|
||||
}
|
||||
|
||||
var (
|
||||
structMap = map[string]interface{}{
|
||||
"name": "gf",
|
||||
"score": 100,
|
||||
}
|
||||
structPointer = new(structType)
|
||||
)
|
||||
|
||||
func Benchmark_Struct_Basic(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Struct(structMap, structPointer)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user