标题好像有点唬人哦….
起因是我在给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是利用原有的底层数组。>_<。
欢迎大牛指点….