追加一个字节数组比 2 字节数组分配的内存要少得多

问题描述 投票:0回答:1

根据下面所示的 Go 基准(通过运行

go test -v -bench=. -benchmem
),将一个字节数组附加到数组中,每次操作需要 1 个分配。

Benchmark_AddOneByteArray-4              1986709           581.2 ns/op      1792 B/op          1 allocs/op

但是,附加 2 字节数组每次操作需要 101 次分配,与附加 32 字节数组(101 次分配)相同

Benchmark_AddTwoByteArray
Benchmark_AddTwoByteArray-4               529726          2235 ns/op        1992 B/op        101 allocs/op
Benchmark_AddThirtyTwoByteArray
Benchmark_AddThirtyTwoByteArray-4         282092          4431 ns/op        4992 B/op        101 allocs/op

为什么附加一字节数组每个操作仅花费 1 次分配,而测试的所有其他大小的每个操作花费 101 次分配?

func addOneByteArray(n int) []any {
    my_array := make([]any, n)

    for i := 0; i < n; i++ {
        my_array[i] = [1]byte{}
    }
    return my_array
}
func addTwoByteArray(n int) []any {
    my_array := make([]any, n)

    for i := 0; i < n; i++ {
        my_array[i] = [2]byte{}
    }
    return my_array
}
func addThirtyTwoByteArray(n int) []any {
    my_array := make([]any, n)

    for i := 0; i < n; i++ {
        my_array[i] = [32]byte{}
    }
    return my_array
}

var N = 100
func Benchmark_AddOneByteArray(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = addOneByteArray(N)
    }
}

func Benchmark_AddTwoByteArray(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = addTwoByteArray(N)
    }
}

func Benchmark_AddThirtyTwoByteArray(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = addThirtyTwoByteArray(N)
    }
}
go benchmarking
1个回答
0
投票

当值可以适合界面表示时,这是对界面的优化。

通常,一个接口被表示为一个带有两个指针的数据块;一个是指向接口元数据的指针,另一个是指向其值的指针。但是,当该值不大于指针时,会进行优化以使该值适合接口块本身。

感谢@rocka2q提供线索。

请注意,这是 golang 运行时代码中的优化,而不是编译器中的优化,因此更改编译器优化选项不会产生影响。

© www.soinside.com 2019 - 2024. All rights reserved.