(Go)不要使用append插入元素

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

標題好像有點唬人哦….
起因是我在給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是利用原有的底層數組。>_<。

歡迎大牛指點….

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.