Golang切片追加与分配性能 [英] Golang slice append vs assign performance
问题描述
要使切片追加操作更快,我们需要分配足够的容量.有两种添加分片的方法,下面是代码:
To make slice append operation faster we need to allocate enough capacity. There's two ways to append slice, Here is the code:
func BenchmarkSliceAppend(b *testing.B) {
a := make([]int, 0, b.N)
for i := 0; i < b.N; i++ {
a = append(a, i)
}
}
func BenchmarkSliceSet(b *testing.B) {
a := make([]int, b.N)
for i := 0; i < b.N; i++ {
a[i] = i
}
}
结果是:
BenchmarkSliceAppend-4 200000000 7.87 ns/op 8 B/op 0 allocs/op
BenchmarkSliceAppend-4 200000000 7.87 ns/op 8 B/op 0 allocs/op
BenchmarkSliceSet-4 300000000 5.76 ns/op 8 B/op
BenchmarkSliceSet-4 300000000 5.76 ns/op 8 B/op
a[i] = i
比a = append(a, i)
快,我想知道为什么吗?
a[i] = i
is faster than a = append(a, i)
and I wanna know why?
推荐答案
a[i] = i
只是将值i
分配给a[i]
.这不是不附加,只是一个简单的分配.
a[i] = i
simply assigns the value i
to a[i]
. This is not appending, it's just a simple assignment.
现在添加:
a = append(a, i)
理论上会发生以下情况:
In theory the following happens:
-
这将调用内置的
append()
函数.为此,它首先必须复制a
切片(切片标头,后备数组不是标头的一部分),并且必须为可变参数创建一个临时切片,该临时切片将包含值i
.
This calls the builtin
append()
function. For that, it first has to copy thea
slice (slice header, backing array is not part of the header), and it has to create a temporary slice for the variadic parameter which will contain the valuei
.
然后,如果像a = a[:len(a)+1]
这样具有足够的容量(在您的情况下具有),则必须重新切片a
-这涉及将新切片分配给append()
中的a
.
(如果a
的容量不足以执行就地"附加操作,则必须分配一个新数组,复制切片中的内容,然后执行assign/append-但情况并非如此.)
Then it has to reslice a
if it has enough capacity (it has in your case) like a = a[:len(a)+1]
- which involves assigning the new slice to a
inside the append()
.
(If a
would not have big enough capacity to do the append "in-place", a new array would have to be allocated, content from slice copied, and then the assign / append be executed - but it is not the case here.)
然后将i
分配给a[len(a)-1]
.
然后从append()
返回新切片,并将此新切片分配给局部变量a
.
Then returns the new slice from append()
, and this new slice is assigned to the local variable a
.
与简单的任务相比,这里发生了很多事情.即使对这些步骤中的许多步骤进行了优化和/或内联,作为将i
分配给切片元素的最低要求,也是切片类型的局部变量a
(这是切片标头)必须在循环的每个周期中更新.
A lot of things happen here compared to a simple assignment. Even if many of these steps are optimized and / or inlined, as a minimum addition to assigning i
to an element of the slice, the local variable a
of slice type (which is a slice header) has to be updated in each cycle of the loop.
推荐阅读: The Go博客:数组,切片(和字符串):追加"的机制
这篇关于Golang切片追加与分配性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!