Golang切片附加vs分配性能

时间:2016-07-29 09:03:00

标签: performance go slice

为了使切片附加操作更快,我们需要分配足够的容量。有两种方法可以附加切片,这是代码:

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

     

BenchmarkSliceSet-4 300000000 5.76 ns / op 8 B / op

a[i] = ia = append(a, i)快,我想知道为什么?

2 个答案:

答案 0 :(得分:7)

a[i] = i只需将值i分配给a[i]即可。这是追加,只是一个简单的assignment

现在追加:

a = append(a, i)

理论上会发生以下情况:

  1. 这会调用内置append()函数。为此,它首先必须复制a切片(切片头,支持数组不是标头的一部分),并且必须为variadic参数创建一个临时切片,该切片将包含值{{1} }。

  2. 如果i具有足够的容量(在您的情况下),则必须重新a,如a = a[:len(a)+1] - 这涉及将新切片分配给a内的append() {1}}。
    (如果a没有足够的容量来执行附加&#34;就地&#34;,则必须分配新数组,复制切片内容,然后分配/附加被执行 - 但这不是这种情况。)

  3. 然后将i分配给a[len(a)-1]

  4. 然后从append()返回新切片,并将此新切片分配给局部变量a

  5. 与简单的任务相比,这里发生了很多事情。即使这些步骤中的许多步骤已经过优化和/或内联,作为将i分配给切片元素的最小额外内容,切片类型的局部变量a (这是一个切片标题)必须在循环的每个循环中更新

    推荐阅读:The Go Blog: Arrays, slices (and strings): The mechanics of 'append'

答案 1 :(得分:4)

自从发布此问题以来,似乎已经引入了Go编译器或运行时的一些改进,因此, path: 'student-profile/:id', canActivate: [StudentProfile], loadChildren: 'app/views/student-post-login/student-profile/student-profile.module#PatientProfileModule' @NgModule({ imports: [ ...... ...... providers: [studentProfile] }) 和按索引直接赋值之间没有显着差异。

此外,由于OOM恐慌,我不得不稍稍更改您的基准测试。

Go 1.10.1

结果:

append