golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.86k stars 17.65k forks source link

x/net/idna: adds 680KiB to binary when imported but unreferenced #38311

Open bradfitz opened 4 years ago

bradfitz commented 4 years ago

I'm working on a Go program in a severely constrained environment and found that I can save 680 KiB of disk (and disk == RAM in this environment) by making sure x/net/idna is never imported (even if unused).

That is, the init tasks for x/net/idna and its deps don't layout in memory such that the linker can discard enough:

package main

import (
        _ "golang.org/x/net/idna"
)

func main() {
        println("hi")
}

It adds 680KiB to binary compared to just the println("hi") line without the import.

Linker says:

dev:underidna $ go build --ldflags=-dumpdep 2>&1 | grep idna
# _/home/bradfitz/tailscale/size-reduce/testidna/underidna
main..inittask -> golang.org/x/net/idna..inittask
golang.org/x/net/idna..inittask -> fmt..inittask
golang.org/x/net/idna..inittask -> strings..inittask
golang.org/x/net/idna..inittask -> golang.org/x/text/secure/bidirule..inittask
golang.org/x/net/idna..inittask -> golang.org/x/text/unicode/bidi..inittask
golang.org/x/net/idna..inittask -> golang.org/x/text/unicode/norm..inittask
golang.org/x/net/idna..inittask -> math..inittask
golang.org/x/net/idna..inittask -> golang.org/x/net/idna.init
golang.org/x/net/idna.init -> golang.org/x/net/idna.idnaSparse
golang.org/x/net/idna.init -> golang.org/x/net/idna.idnaSparseValues
golang.org/x/net/idna.init -> golang.org/x/net/idna.idnaSparseOffset
golang.org/x/net/idna.idnaSparseOffset -> golang.org/x/net/idna..stmp_8
golang.org/x/net/idna.idnaSparseValues -> type.[1997]golang.org/x/net/idna.valueRange
golang.org/x/net/idna.idnaSparse -> type.golang.org/x/net/idna.sparseBlocks
golang.org/x/net/idna..stmp_8 -> type.[276]uint16
type.golang.org/x/net/idna.sparseBlocks -> type..namedata.*idna.sparseBlocks-
type.golang.org/x/net/idna.sparseBlocks -> type.*golang.org/x/net/idna.sparseBlocks
type.golang.org/x/net/idna.sparseBlocks -> type..importpath.golang.org/x/net/idna.
type.golang.org/x/net/idna.sparseBlocks -> type..namedata.values-
type.golang.org/x/net/idna.sparseBlocks -> type.[]golang.org/x/net/idna.valueRange
type.*golang.org/x/net/idna.sparseBlocks -> type..namedata.lookup-
type.[]golang.org/x/net/idna.valueRange -> type..namedata.*[]idna.valueRange-
type.[]golang.org/x/net/idna.valueRange -> type.golang.org/x/net/idna.valueRange
type.golang.org/x/net/idna.valueRange -> type..namedata.*idna.valueRange-
type.golang.org/x/net/idna.valueRange -> type.*golang.org/x/net/idna.valueRange
type.[1997]golang.org/x/net/idna.valueRange -> type..eqfunc7988
type.[1997]golang.org/x/net/idna.valueRange -> type..namedata.*[1997]idna.valueRange-

/cc @randall77 @mpvl @rsc @ianlancetaylor

rasky commented 4 years ago

Related: #19533 #14840

bradfitz commented 4 years ago

Also related: #38450 (lazy imports proposal)