本公众号曾发表过一篇文章:使用append来克隆切片常常比使用copy高效得多。但是Go官方工具链在1.15版本中对后者(即使用make+copy来来克隆切片)做了优化(具体来说就是make之后不对刚开出来的元素清零,因为后续的copy将覆盖这些元素)。
所以当使用官方工具链1.15+编译Go程序时,此原先的结论不仅不再成立,而且还反转了。也就说使用make+copy来克隆切片总是比使用append克隆要快。这里要快的原因是使用append来克隆切片可能会产生一些多余的容量。
有benchmarks为证:
package main
import "testing"
const N = 1024 * 1024
type Element = int64
var xForMake = make([]Element, N)
var xForMakeCopy = make([]Element, N)
var xForAppend = make([]Element, N)
var yForMake []Element
var yForMakeCopy []Element
var yForAppend []Element
func Benchmark_PureMake(b *testing.B) {
for i := 0; i < b.N; i++ {
yForMake = make([]Element, N)
}
}
func Benchmark_MakeAndCopy(b *testing.B) {
for i := 0; i < b.N; i++ {
yForMakeCopy = make([]Element, N)
copy(yForMakeCopy, xForMakeCopy)
}
}
func Benchmark_Append(b *testing.B) {
for i := 0; i < b.N; i++ {
yForAppend = append([]Element(nil), xForAppend...)
}
}
结果:
$ go version
go version go1.15 linux/amd64
$ go test -bench=. -benchtime=3s
goos: linux
goarch: amd64
Benchmark_PureMake-4 4027 872563 ns/op
Benchmark_MakeAndCopy-4 4614 756891 ns/op
Benchmark_Append-4 4695 760042 ns/op
从结果可以看出,make+copy甚至比一个单make都快(因为单make需要对元素清零,而且此清零操作尚未被优化)。
参考:
https://github.com/golang/go/issues/26252
https://github.com/golang/go/issues/14718
推荐阅读
站长 polarisxu
自己的原创文章
不限于 Go 技术
职场和创业经验
Go语言中文网
每天为你
分享 Go 知识
Go爱好者值得关注