【问题标题】:extra allocation when returning interface{} instead of int64返回 interface{} 而不是 int64 时的额外分配
【发布时间】:2018-01-03 03:25:03
【问题描述】:

我有一个函数可以生成一个随机的int64 并将其作为interface{} 返回,如下所示:

func Val1(rnd rand.Source) interface{} {
 return rnd.Int63() 
} 

现在考虑这个函数,它做同样的事情但返回一个int64

func Val2(rnd rand.Source) int64 {
 return rnd.Int63()
}

我用这个(go test -bench=. -benchmem)对这两个函数进行了基准测试:

func BenchmarkVal1(b *testing.B) {
    var rnd = rand.NewSource(time.Now().UnixNano())
    for n := 0; n < b.N; n++ {
        Val1(rnd)
    }
}

func BenchmarkVal2(b *testing.B) {
    var rnd = rand.NewSource(time.Now().UnixNano())
    for n := 0; n < b.N; n++ {
        Val2(rnd)
    }
}

得到以下结果:

BenchmarkVal1-4    50000000         32.4 ns/op         8 B/op          1 allocs/op
BenchmarkVal2-4    200000000        7.47 ns/op         0 B/op          0 allocs/op

Val1() 中的额外分配从何而来?返回 interface{} 时可以避免吗?

【问题讨论】:

    标签: object memory go types allocation


    【解决方案1】:

    接口值是底层的包装器,一对存储在接口值中的具体值及其类型描述符。

    阅读本文了解更多信息:The Laws of Reflection #The representation of an interface

    所以如果你想返回一个interface{}类型的值,一个interface{}值将被隐式创建(如果返回的值还不是那个类型),它将保存整数及其类型描述符表示int64 类型。这是你无法避免的。

    interface{} 是一种特殊的接口类型(有 0 个方法)。正如您在基准输出中看到的那样,它的值只有 8 个字节。其他接口类型的尺寸更大(双倍),因为它们还必须识别接口类型的静态方法集(动态类型和值除外)。

    还请务必查看这个内容丰富的答案:Go: What's the meaning of interface{}?

    如果你想了解更多关于实现/内部的信息,我推荐这篇文章:How Interfaces Work in Golang

    【讨论】:

    • 和往常一样@icza,你值得拥有你的黄金重量
    猜你喜欢
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 2022-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多