为什么通过可变参数的速度如此之慢?

Why is it so badly slow to pass variadic arguments?

提问人:xmllmx 提问时间:7/2/2023 最后编辑:xmllmx 更新时间:7/2/2023 访问量:91

问:

package main

import (
    "fmt"
    "time"
)

func main() {

    n := 1024
    dst1 := make([]byte, n)
    dst2 := make([]byte, 0, n)
    dst3 := make([]byte, 0, n)

    start := time.Now()
    for i := 0; i < n; i++ {
        dst1[i] = byte(i)
    }
    fmt.Println(uint64(time.Since(start).Microseconds()))

    start = time.Now()
    for i := 0; i < n; i++ {
        dst2 = append(dst2, dst1[i])
    }
    fmt.Println(uint64(time.Since(start).Microseconds()))

    start = time.Now()
    for i := 0; i < n; i++ {
        dst3 = append(dst3, dst1...)
    }
    fmt.Println(uint64(time.Since(start).Microseconds()))
}

基准测试结果:

2
2  
2711

为什么通过可变参数的速度如此之慢?

performance go 参数传递 可变函数 惯用语

评论

1赞 Volker 7/2/2023
这与可变参数无关。您应该使用包测试中的基准测试。

答:

5赞 NubDev 7/2/2023 #1

最后一个 for 循环使用 append 将较大的“dst3”切片多次添加到“dst1”切片中。这需要更多的时间,因为每次迭代都涉及将整个“dst3”切片复制到“dst1”切片。

评论

0赞 Dmitry Harnitski 7/3/2023
答案是正确的,我只想澄清一些技术细节。内存是复制的,而不是在每次迭代时复制的。仅当切片大小达到其容量时,才会移动它。go.dev/blog/slices