为什么这段代码在Go语言中生成的可执行文件非常大(大约81M)?

huangapple go评论78阅读模式
英文:

Why this code generate very big executable in go (around 81M)?

问题

我是你的中文翻译助手,以下是你提供的代码的翻译:

我对golang还不熟悉。我写了如下的代码:

package main

import (
	"fmt"
)

const (
	BIG_NUM = 10 * 1000 * 1000
)

type BigData [BIG_NUM]uint64

func (self BigData) String() string {
	return fmt.Sprintf("%d\n", self[0])
}

func (self *BigData) Clear() {
	*self = BigData{}
}

func main() {
	data := new(BigData)
	fmt.Println(data)
}

编译后,可执行文件大小约为81M:

$ ls -l
-rwxr-xr-x  1 tchen  522017917  81533376 Dec 19 08:44 test
-rw-r--r--  1 tchen  522017917       290 Dec 19 08:44 test.go

当我移除Clear()函数时,可执行文件大小恢复正常。为什么Clear()函数会生成如此大的可执行文件?它应该在运行时调用,而不是编译时调用,对吗?

------------ 进一步调查 -----------

受@FUZxxl的启发,我修改了代码,在Clear()函数中使用了一个全局变量。这次文件大小恢复正常了。所以全局变量被正确地放置在.bss段中。

package main

import (
	"fmt"
)

const (
	BIG_NUM = 10 * 1000 * 1000
)

type BigData [BIG_NUM]uint64

var (
	bigData = BigData{}
)

func (self BigData) String() string {
	return fmt.Sprintf("%d\n", self[0])
}

func (self *BigData) Clear() {
	*self = bigData
}

func main() {
	data := new(BigData)
	fmt.Println(data)
}

编译后的可执行文件:

$ ls -l
-rwxr-xr-x  1 tchen  522017917  1534384 Dec 19 10:55 test
-rw-r--r--  1 tchen  522017917      318 Dec 19 10:55 test.go

------------ 最新更新 -----------

到目前为止,看起来这是一个编译器问题。已经提交了一个bug报告:https://code.google.com/p/go/issues/detail?id=6993。如果你感兴趣,可以跟进一下。

在找到解决方案之前,你应该避免在函数中使用x := Y{}的方式。一个解决方法是(感谢ality@pbrane.org):

func (self *BigData) Clear() {
	var zero BigData
	*self = zero
}
英文:

I'm new to golang. I wrote code like this:

package main

import (
	"fmt"
)

const (
	BIG_NUM = 10 * 1000 * 1000
)

type BigData [BIG_NUM]uint64

func (self BigData) String() string {
	return fmt.Sprintf("%d\n", self[0])
}

func (self *BigData) Clear() {
	*self = BigData{}
}

func main() {
	data := new(BigData)
	fmt.Println(data)
}

After compiling, the executable is around 81M:

$ ls -l
-rwxr-xr-x  1 tchen  522017917  81533376 Dec 19 08:44 test
-rw-r--r--  1 tchen  522017917       290 Dec 19 08:44 test.go

When I remove Clear() function, the executable goes to normal size. So why this Clear() function generate so big executable? It should be called at runtime, not compiling time, right?

------------ further investigation -----------

Enlightened by @FUZxxl, I modified the code to use a global variable in Clear(). This time the file size went back to normal. So global variables are putting to .bss section correctly.

package main

import (
	"fmt"
)

const (
	BIG_NUM = 10 * 1000 * 1000
)

type BigData [BIG_NUM]uint64

var (
	bigData = BigData{}
)

func (self BigData) String() string {
	return fmt.Sprintf("%d\n", self[0])
}

func (self *BigData) Clear() {
	*self = bigData
}

func main() {
	data := new(BigData)
	fmt.Println(data)
}

The compiled executable:

$ ls -l
-rwxr-xr-x  1 tchen  522017917  1534384 Dec 19 10:55 test
-rw-r--r--  1 tchen  522017917      318 Dec 19 10:55 test.go

------------ latest update -----------

So far it seems this is a compiler issue. A bug has been submitted: https://code.google.com/p/go/issues/detail?id=6993. You can follow up it if you're interested.

Before there's any solution to it, you should avoid using x := Y{} in your function. A workaround is (thanks to ality@pbrane.org):

func (self *BigData) Clear() {
-	*self = BigData{}
+	var zero BigData
+	*self = zero
} 

答案1

得分: 10

Clear()函数中,BigData{}似乎导致一个大小为80,000,000字节的数组被硬编码到二进制文件中,其大小为sizeof uint64 * 10 * 1000 * 1000

英文:

Looks like BigData{} in the Clear() function is causing an array of 80,000,000 bytes = sizeof uint64 * 10 * 1000 * 1000 to be hardcoded into the binary.

huangapple
  • 本文由 发表于 2013年12月19日 08:48:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/20671535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定