You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
When reflect's Method is used with a non-constant argument, the linker has to keep every public method of reachable types because it can't statically determine whether that method will be called through reflect. This makes binaries significantly bigger (in my experience, around 30%). https://github.com/golang/go/blob/go1.23.6/src/cmd/link/internal/ld/deadcode.go#L420-L433
github.com/google/go-cmp uses reflect.Type.Method to generate a string representation of an unnamed interface type (source), which disables this dead code elimination.
Since go-cmp is used by various k8s packages, you can't avoid it when using those dependencies.
Adding a build tag to optionally replace the logic of generating a string representation of an unnamed interface, from using reflect.Type.Method() to using reflect.Type.String(). The main issue is that it changes the generated string (in particular it wouldn't follow the qualified argument), and I'm not sure how much of an issue that would be. Add a build tag to avoid disabling dead code elimination #375
I think 1. should be done as it fixes the issue by default for users of Equal without any functional change (except an extra space character), and 2. if you're fine with it would allow users who care to also fix Diff (assuming the proposed change is safe and wouldn't break any functionality).
Additional notes
This is somewhat similar to spf13/cobra#2015 for cobra.
Describe the bug
When
reflect'sMethodis used with a non-constant argument, the linker has to keep every public method of reachable types because it can't statically determine whether that method will be called throughreflect. This makes binaries significantly bigger (in my experience, around 30%).https://github.com/golang/go/blob/go1.23.6/src/cmd/link/internal/ld/deadcode.go#L420-L433
github.com/google/go-cmpusesreflect.Type.Methodto generate a string representation of an unnamed interface type (source), which disables this dead code elimination.Since
go-cmpis used by various k8s packages, you can't avoid it when using those dependencies.To Reproduce
Consider this simple example:
When building with upstream
go-cmp, the binary is 6.6MB.When using the build tag added on my branch, the binary is 5.1MB.
The binary is 30% bigger when DCE is disabled.
Fixing
I propose two ways of fixing this issue.
The
Equalfunction can be fixed by moving code around, so that the linker can statically determine that the problematic piece of code is not reachable. Avoid disabling dead code elimination when using Equal #374Adding a build tag to optionally replace the logic of generating a string representation of an unnamed interface, from using
reflect.Type.Method()to usingreflect.Type.String(). The main issue is that it changes the generated string (in particular it wouldn't follow thequalifiedargument), and I'm not sure how much of an issue that would be.Add a build tag to avoid disabling dead code elimination #375
I think 1. should be done as it fixes the issue by default for users of
Equalwithout any functional change (except an extra space character), and 2. if you're fine with it would allow users who care to also fixDiff(assuming the proposed change is safe and wouldn't break any functionality).Additional notes
This is somewhat similar to spf13/cobra#2015 for
cobra.