這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
標題好像有點唬人哦….
起因是我在給Slice做Insert函數,給幾個版本封裝時做了一些效能測試。結果出人意料!
import ( "fmt" "reflect" "time")func copyInsert(slice interface{}, pos int, value interface{}) interface{} { v := reflect.ValueOf(slice) v = reflect.Append(v, reflect.ValueOf(value)) reflect.Copy(v.Slice(pos+1, v.Len()), v.Slice(pos, v.Len())) v.Index(pos).Set(reflect.ValueOf(value)) return v.Interface()}func Insert(slice interface{}, pos int, value interface{}) interface{} { v := reflect.ValueOf(slice) ne := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(value)), 1, 1) ne.Index(0).Set(reflect.ValueOf(value)) v = reflect.AppendSlice(v.Slice(0, pos), reflect.AppendSlice(ne, v.Slice(pos, v.Len()))) return v.Interface()}func main() { slice := []int{1, 2} slice2 := []int{1, 2} slice3 := []int{1, 2} t0 := time.Now() for i := 1; i < 10000; i++ { slice = append(slice[:1], append([]int{i}, slice[1:]...)...) } t1 := time.Now() for i := 1; i < 10000; i++ { slice2 = Insert(slice2, 1, i).([]int) } t2 := time.Now() for i := 1; i < 10000; i++ { slice3 = copyInsert(slice3, 1, i).([]int) // fmt.Println(slice3) } t3 := time.Now() //元素檢測 for i := 0; i < 10000; i++ { if slice[i] != slice2[i] || slice2[i] != slice3[i] { fmt.Println("error") } } fmt.Println("reflect append insert:", t2.Sub(t1), "append insert: ", t1.Sub(t0), "copy Insert: ", t3.Sub(t2))}
輸出結果
reflect append insert: 273.276271ms append insert: 195.938231ms copy Insert: 29.626058ms
利用反射的reflect比普通append尚可理解,但居然比copy Instert慢了10倍。>_<。
我不信啊,於是再做了測試
import ( "fmt" "time")func main() { s1 := []int{1, 2, 3} s2 := []int{1, 2, 3} //每次插入第三個 t1 := time.Now() for i := 0; i < 10000; i++ { s1 = append(s1[0:3], append([]int{i}, s1[3:]...)...) } t2 := time.Now() //每次插入第三個 for i := 0; i < 10000; i++ { s2 = append(s2, i) copy(s2[3:len(s2)], s2[2:len(s2)-1]) s2[3] = i } t3 := time.Now() //檢測錯誤 for i := 0; i < len(s1); i++ { if s1[i] != s2[i] { fmt.Println("error") } } fmt.Println(t3.Sub(t2), t2.Sub(t1))}
輸出結果
copy instert: 21.245765ms append insert: 189.930674ms
結果還是差了十倍哎!
猜測:兩次append()的時候,做slice切片會產生底層數組複製。(append([]int{i}, s1[3:]…)),但s1很大的時候,複製的越多,效能越差,而copy是利用原有的底層數組。>_<。
歡迎大牛指點….