gpt4 book ai didi

go - 内联和输出二进制大小

转载 作者:数据小太阳 更新时间:2023-10-29 03:23:46 25 4
gpt4 key购买 nike

package main

type TreeCell struct {
Tabs func() *string
}

func Cell() *string {
s:= ""
return &s
}

func Table(Line *[]TreeCell) {
if Line != nil {
Num["rtt"] = Line
}
}

var (
Num map[string]*[]TreeCell
)

func main() {

Table(&[]TreeCell{
TreeCell{Tabs: Cell},
TreeCell{Tabs: Cell},
...repeat 15000 times
TreeCell{Tabs: Cell},
})
}

go build -a -v -gcflags "-N -l"-ldflags "-s -w"

可执行文件的大小 1,9Mb

__text              1459891   16781312
__rodata 158107 18241216
Total 1951521

如果我将 func() *string 更改为 interface{}

type TreeCell struct {
Tabs interface{}
}

那么可执行文件的大小为32Mb

__text               1864389   16781312
__rodata 30375699 18645728
Total 32698219

为什么?

Go 版本 1.9.2

最佳答案

interface{} 变量的大小为 8 或 16 字节(取决于架构是 32 位还是 64 位),函数变量的大小为 4 或 8 字节。所以只有一个 2 乘法,这无法解释输出二进制文件中的巨大差异(15.000 * 8 字节仅为 120 KB)。

您所体验到的是不同内联 编译器优化的结果。 Cell() 函数非常简单,可以内联。

禁用内联时

如果我们在您的示例中包含 -gcflags '-N -l' 参数(这些标志告诉编译器禁用内联),那么对 Cell 的引用是没有内联,所以使用 func() *string 只会使用一个 4 字节的函数指针。

但是,使用 interface{} 将导致内联 Cell 值。接口(interface)值保存一个副本,并且函数调用不是内联的,但是当函数值被隐式包装在 interface{} 值中时被使用时,它是内联的(重复的)。每一次,就是一万五千次!所以基本上 Cell() 函数体被包含了 15.000 次。现在它很大,这就是生成的二进制文件有 30 MB 的原因。

启用内联时

如果我们排除 -gcflags '-N -l' 参数,实际上是相反的:使用 interface{ 时编译的二进制文件大约为 2 MB },使用func () *string时大约是30MB。

这次在复合文字中使用Cell 函数值初始化TreeCell.Tabs 字段时,编译器将内联Cell() 函数总共 15.000 次!但是,在使用 interface{} 时,不会内联函数体。不知道为什么,一个可能的解释是它在 interface{} 的情况下也是内联的,并且由于接口(interface)值是不可变的,所以相同的值被使用了 15.000 次。

关于go - 内联和输出二进制大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47968970/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com