Go: cmd/compile: binary size explodes for huge return value

Created on 21 Apr 2020  路  5Comments  路  Source: golang/go

What version of Go are you using (go version)?

$ go version
go version go1.14.2 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

go env Output

$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/user/.cache/go-build"
GOENV="/home/user/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/user"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/user/src/golang.org/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/user/src/golang.org/go/pkg/tool/linux_amd64"
GCCGO="/usr/bin/gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build845352725=/tmp/go-build -gno-record-gcc-switches"

What did you do?

$ cat <<EOF > a.go
package main

import (
    "fmt"
)

type foo struct {
    data [256 * 256 * 256 * 32]byte
}

func f() foo {
    return foo{}
}
func main() {
    x := f()
    fmt.Println("%v", x.data[0])
}
EOF

$ go build a.go

https://play.golang.org/p/OZpuS_MxVNx

What did you expect to see?

A binary file less than 2MB.

What did you see instead?

A binary file of ~514MiB size.

For what it's worth, gccgo produces a sane binary (38KiB, dynamic linking).

NeedsInvestigation Performance

Most helpful comment

""..stmp_0 SRODATA size=536870912
""..stmp_2 SRODATA size=536870912

There are some really big static temps used to initialize instances of type foo. One at the return site of foo (which goes away because foo is inlined?) and one in main to initialize the heap-allocated foo (the compiler heap allocates x because it is too large).

We shouldn't be copying from zeroed data to initialize anything - we should just zero it directly.

An easier fix would be to allocated all-zero static temps in BSS, so at least they don't bloat the binary.

All 5 comments

""..stmp_0 SRODATA size=536870912
""..stmp_2 SRODATA size=536870912

There are some really big static temps used to initialize instances of type foo. One at the return site of foo (which goes away because foo is inlined?) and one in main to initialize the heap-allocated foo (the compiler heap allocates x because it is too large).

We shouldn't be copying from zeroed data to initialize anything - we should just zero it directly.

An easier fix would be to allocated all-zero static temps in BSS, so at least they don't bloat the binary.

It seems that disabling this section of code can avoid the problem.

I have a fix in the works.

Change https://golang.org/cl/229704 mentions this issue: cmd/compile: optimize Move with all-zero ro sym src to Zero

Change https://golang.org/cl/229707 mentions this issue: cmd/compile: avoid double-zeroing

Was this page helpful?
0 / 5 - 0 ratings