Skip to content

cmd/compile: binary size increase from generics #70045

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
andig opened this issue Oct 25, 2024 · 6 comments
Closed

cmd/compile: binary size increase from generics #70045

andig opened this issue Oct 25, 2024 · 6 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@andig
Copy link
Contributor

andig commented Oct 25, 2024

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

$ go version
go version go1.23.2 darwin/arm64

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=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/andig/Library/Caches/go-build'
GOENV='/Users/andig/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/andig/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/andig/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.23.2/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.23.2/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.23.2'
GODEBUG=''
GOTELEMETRY='on'
GOTELEMETRYDIR='/Users/andig/Library/Application Support/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/andig/htdocs/evcc/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/sv/rs_453y57xj86xsbz3kw1mbc0000gn/T/go-build1030719432=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOROOT/bin/go version: go version go1.23.2 darwin/arm64
GOROOT/bin/go tool compile -V: compile version go1.23.2
uname -v: Darwin Kernel Version 24.0.0: Tue Sep 24 23:36:26 PDT 2024; root:xnu-11215.1.12~1/RELEASE_ARM64_T8103
ProductName:		macOS
ProductVersion:		15.0.1
BuildVersion:		24A348
lldb --version: lldb-1600.0.36.3
Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)

What did you do?

Replace for loop with generic function.

Before:

func (vv *vehicles) Instances() []api.Vehicle {
	devs := config.Vehicles().Devices()

	res := make([]api.Vehicle, 0, len(devs))
	for _, dev := range devs {
		res = append(res, dev.Instance())
	}

	return res
}

After:

func (vv *vehicles) Instances() []api.Vehicle {
	return lo.Map(config.Vehicles().Devices(), func(dev config.Device[api.Vehicle], _ int) api.Vehicle {
		return dev.Instance()
	})
}

with lo.Map simply being (samber/lo):

func Map[T any, R any](collection []T, iteratee func(item T, index int) R) []R {
	result := make([]R, len(collection))

	for i := range collection {
		result[i] = iteratee(collection[i], i)
	}

	return result
}

What did you expect to see?

Similar or smaller binary size

What did you see instead?

Binary size increased by 14kib for a single function call.

Before:

97417010

After:

97433586
@seankhliao seankhliao changed the title Generics binary size compilation efficiency cmd/compile: binary size increase from generics Oct 25, 2024
@seankhliao
Copy link
Member

do you have a self contained reproducer?

@seankhliao seankhliao added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Oct 25, 2024
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Oct 25, 2024
@andig
Copy link
Contributor Author

andig commented Oct 25, 2024

The repo is open source but a bit complex. Synthetic example yields additional 400 bytes, not sure that's relevant?

package main

import _ "github.com/samber/lo"

type element struct {
	value string
}

func (c *element) Value() string {
	return c.value
}

func main() {
	var list []element

	// 2953986 bytes
	res := make([]string, 0, len(list))
	for _, el := range list {
		res = append(res, el.Value())
	}

	// 2954306 bytes
	// res := lo.Map(list, func(el element, _ int) string {
	// 	return el.Value()
	// })

	_ = res
}

Could I produce any kind of export data that might be helpful?

@andig
Copy link
Contributor Author

andig commented Oct 25, 2024

Another attempt (replacing main.go of https://github.com/evcc-io/evcc):

package main

import (
	"github.com/evcc-io/evcc/api"
	"github.com/evcc-io/evcc/util/config"
	"github.com/samber/lo"
)

type vehicles struct{}

// 9960802 bytes
// func (vv *vehicles) Instances() []api.Vehicle {
// 	devs := config.Vehicles().Devices()

// 	res := make([]api.Vehicle, 0, len(devs))
// 	for _, dev := range devs {
// 		res = append(res, dev.Instance())
// 	}

// 	return res
// }

// 9961538 bytes
func (vv *vehicles) Instances() []api.Vehicle {
	return lo.Map(config.Vehicles().Devices(), func(dev config.Device[api.Vehicle], _ int) api.Vehicle {
		return dev.Instance()
	})
}

func main() {
	var vv vehicles
	_ = vv.Instances()
}

Again only a 700 bytes difference.

@seankhliao
Copy link
Member

looks like you have something other than generics that's increasing your binary size

Unlike many projects, the Go project does not use GitHub Issues for general discussion or asking questions. GitHub Issues are used for tracking bugs and proposals only.

For questions please refer to https://github.com/golang/go/wiki/Questions

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Oct 25, 2024
@andig
Copy link
Contributor Author

andig commented Oct 25, 2024

Appreciate the feedback. If you want to take the time- any idea what could increase binary size when only this single function is being updated? Is there any AST or similar of the compiled program that I could export for inspection? Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

4 participants