首页 >后端开发 >Golang >为什么将'interface{}”转换回切片会导致额外的堆分配?

为什么将'interface{}”转换回切片会导致额外的堆分配?

PHPz
PHPz转载
2024-02-12 22:15:09795浏览

为什么将interface{}”转换回切片会导致额外的堆分配?

在PHP中,将“interface{}”类型转换为切片(slice)类型时,会导致额外的堆分配。这是因为在PHP中,接口(interface)是一种抽象的数据类型,而切片是一种动态数组类型。当我们将接口类型转换为切片类型时,PHP需要为切片类型分配额外的内存空间来存储切片的元素。这个额外的堆分配操作会导致内存的额外开销,对于一些内存敏感的应用程序来说,可能会带来性能问题。因此,在进行类型转换时,我们应该注意这个问题,尽量避免不必要的额外堆分配。

问题内容

func benchmarkpool(b *testing.b) {
    b.reportallocs()
    p := sync.pool{new: func() interface{} {
        return make([]byte, 1024)
    }}
    for i := 0; i < b.n; i++ {
        bts := p.get().([]byte)
        p.put(bts)
    }
}

该基准测试在 go1.19.5 中给出以下输出。

benchmarkpool
benchmarkpool-10        47578498            24.47 ns/op       24 b/op          1 allocs/op

当使用 *[]byte 时,事情会变得不同:

func benchmarkpool(b *testing.b) {
    b.reportallocs()
    p := sync.pool{new: func() interface{} {
        bts := make([]byte, 1024)
        return &bts
    }}
    for i := 0; i < b.n; i++ {
        bts := p.get().(*[]byte)
        p.put(bts)
    }
}
BenchmarkPool
BenchmarkPool-10        142008002            8.581 ns/op           0 B/op          0 allocs/op

似乎将 interface{} 转换回切片会导致额外的堆分配。

为什么 go 需要这个额外的分配?其背后的设计考虑是什么?

解决方法

造成分配的不是 any[]byte 的转换,而是 []byteany 的转换。 p.Put(bts) 将参数 bts 隐式转换为 any,然后再将其传递给 (*sync.Pool).Put。 GoGC 1.19 中的接口被实现为一对指针,一个指向类型元数据,一个指向实际对象,在这种情况下,第二个指针转义到池,导致分配切片对象。这不仅适用于切片类型,也适用于任何其他非指针类型。

对于指针,例如 *[]byte,编译器会执行优化,将其值直接放入 iface 结构中,从而在转换为接口时删除 *[]byte,编译器会执行优化,将其值直接放入 iface 结构中,从而在转换为接口时删除

实例的分配。因此,通常建议将指针放入池中而不是结构本身。🎜

以上是为什么将'interface{}”转换回切片会导致额外的堆分配?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文转载于:stackoverflow.com。如有侵权,请联系admin@php.cn删除