首页 > 后端开发 > Golang > 正文

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

PHPz
发布: 2024-02-12 22:15:09
转载
719 人浏览过

为什么将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
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!