From 21f48d375048c216589eb145701a3cc64bc82a89 Mon Sep 17 00:00:00 2001 From: John Guo Date: Wed, 30 Mar 2022 14:32:16 +0800 Subject: [PATCH] improve Unique function performance for normal arrays --- container/garray/garray_normal_any.go | 27 ++++++++++++++++++--------- container/garray/garray_normal_int.go | 27 ++++++++++++++++++--------- container/garray/garray_normal_str.go | 27 ++++++++++++++++++--------- database/gdb/gdb_func.go | 6 +++--- os/gtime/gtime.go | 6 +++--- 5 files changed, 60 insertions(+), 33 deletions(-) diff --git a/container/garray/garray_normal_any.go b/container/garray/garray_normal_any.go index 840193b5e..b8348ff25 100644 --- a/container/garray/garray_normal_any.go +++ b/container/garray/garray_normal_any.go @@ -503,16 +503,25 @@ func (a *Array) Search(value interface{}) int { // Example: [1,1,2,3,2] -> [1,2,3] func (a *Array) Unique() *Array { a.mu.Lock() - for i := 0; i < len(a.array)-1; i++ { - for j := i + 1; j < len(a.array); { - if a.array[i] == a.array[j] { - a.array = append(a.array[:j], a.array[j+1:]...) - } else { - j++ - } - } + defer a.mu.Unlock() + if len(a.array) == 0 { + return a } - a.mu.Unlock() + var ( + ok bool + temp interface{} + uniqueSet = make(map[interface{}]struct{}) + uniqueArray = make([]interface{}, 0, len(a.array)) + ) + for i := 0; i < len(a.array); i++ { + temp = a.array[i] + if _, ok = uniqueSet[temp]; ok { + continue + } + uniqueSet[temp] = struct{}{} + uniqueArray = append(uniqueArray, temp) + } + a.array = uniqueArray return a } diff --git a/container/garray/garray_normal_int.go b/container/garray/garray_normal_int.go index 4ee8a21a0..a3d09b0e5 100644 --- a/container/garray/garray_normal_int.go +++ b/container/garray/garray_normal_int.go @@ -514,16 +514,25 @@ func (a *IntArray) Search(value int) int { // Example: [1,1,2,3,2] -> [1,2,3] func (a *IntArray) Unique() *IntArray { a.mu.Lock() - for i := 0; i < len(a.array)-1; i++ { - for j := i + 1; j < len(a.array); { - if a.array[i] == a.array[j] { - a.array = append(a.array[:j], a.array[j+1:]...) - } else { - j++ - } - } + defer a.mu.Unlock() + if len(a.array) == 0 { + return a } - a.mu.Unlock() + var ( + ok bool + temp int + uniqueSet = make(map[int]struct{}) + uniqueArray = make([]int, 0, len(a.array)) + ) + for i := 0; i < len(a.array); i++ { + temp = a.array[i] + if _, ok = uniqueSet[temp]; ok { + continue + } + uniqueSet[temp] = struct{}{} + uniqueArray = append(uniqueArray, temp) + } + a.array = uniqueArray return a } diff --git a/container/garray/garray_normal_str.go b/container/garray/garray_normal_str.go index 2a33b3d2a..9601e3b8d 100644 --- a/container/garray/garray_normal_str.go +++ b/container/garray/garray_normal_str.go @@ -516,16 +516,25 @@ func (a *StrArray) Search(value string) int { // Example: [1,1,2,3,2] -> [1,2,3] func (a *StrArray) Unique() *StrArray { a.mu.Lock() - for i := 0; i < len(a.array)-1; i++ { - for j := i + 1; j < len(a.array); { - if a.array[i] == a.array[j] { - a.array = append(a.array[:j], a.array[j+1:]...) - } else { - j++ - } - } + defer a.mu.Unlock() + if len(a.array) == 0 { + return a } - a.mu.Unlock() + var ( + ok bool + temp string + uniqueSet = make(map[string]struct{}) + uniqueArray = make([]string, 0, len(a.array)) + ) + for i := 0; i < len(a.array); i++ { + temp = a.array[i] + if _, ok = uniqueSet[temp]; ok { + continue + } + uniqueSet[temp] = struct{}{} + uniqueArray = append(uniqueArray, temp) + } + a.array = uniqueArray return a } diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index ed54bd65f..a687c4dbb 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -181,12 +181,12 @@ func DataToMapDeep(value interface{}) map[string]interface{} { return m } -// doHandleTableName adds prefix string and quote chars for the table. It handles table string like: +// doHandleTableName adds prefix string and quote chars for table name. It handles table string like: // "user", "user u", "user,user_detail", "user u, user_detail ut", "user as u, user_detail as ut", // "user.user u", "`user`.`user` u". // -// Note that, this will automatically checks the table prefix whether already added, if true it does -// nothing to the table name, or else adds the prefix to the table name. +// Note that, this will automatically check the table prefix whether already added, if true it does +// nothing to the table name, or else adds the prefix to the table name and returns new table name with prefix. func doHandleTableName(table, prefix, charLeft, charRight string) string { var ( index = 0 diff --git a/os/gtime/gtime.go b/os/gtime/gtime.go index e3968281c..dc9c48d0f 100644 --- a/os/gtime/gtime.go +++ b/os/gtime/gtime.go @@ -454,10 +454,10 @@ func ParseDuration(s string) (duration time.Duration, err error) { } // FuncCost calculates the cost time of function `f` in nanoseconds. -func FuncCost(f func()) int64 { - t := TimestampNano() +func FuncCost(f func()) time.Duration { + t := time.Now() f() - return TimestampNano() - t + return time.Now().Sub(t) } // isTimestampStr checks and returns whether given string a timestamp string.