-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
cmd/compile: long function names due to generic instantiation with large struct types #65030
Comments
I think the root of the problem is that we're picking the underlying type of a given type T when forming the shape type for it, as in this code: This is eminently sensible (I might even go so far to say required) in a majority of the cases (since obviously we want to common up named types whose underlying types are the same), but in the case of huge structures with very long link strings it's a problem. I will send a tentative CL shortly to switch to using the type hash instead. |
Change https://go.dev/cl/554975 mentions this issue: |
👍 this issue affects pprof, I had a profile with a function name bigger than the screen at default zoom level once. |
Shape-based stenciling in the Go compiler's generic instantiation phase looks up shape types using the underlying type of a given target type. This has a beneficial effect in most cases (e.g. we can use the same shape type for two different named types whose underlying type is "int"), but causes some problems when the underlying type is a very large structure. The link string for the underlying type of a large imported struct can be extremely long, since the link string essentially enumerates the full package path for every field type; this can produce a "go.shape.struct { ... " symbol name that is absurdly long. This patch switches the compiler to use a hash of the underlying type link string instead of the string itself, which should continue to provide commoning but keep symbol name lengths reasonable for shape types based on large imported structs. Fixes golang#65030. Change-Id: I87d602626c43172beb99c186b8ef72327b8227a2 Reviewed-on: https://go-review.googlesource.com/c/go/+/554975 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Than McIntosh <thanm@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Go version
go version devel go1.22-b702e0438a Mon Jan 8 20:15:52 2024 +0000 darwin/arm64
Output of
go env
in your module/workspace:What did you do?
Build this program:
https://go.dev/play/p/6Jsq0rUhQ9K
Source:
and examine the assembly (gcflags=-S).
What did you see happen?
At the call to slices.Insert in main function, here is an assembly fragment (from "go build -gcflags=-S -trimpath main.go"):
The program works properly, but note the name for the instantiated version of
slices.Insert
, which is almost 600 characters long. Of particular concern is that although the generic function is instantiated with the typeexec.Cmd
, the function name looks like it refers to an anonymous struct type that has all the fields ofcmd.Exec
, but in which all the field names/types are spelled out (including package paths, etc).In this example, the long function name is not that big a deal, but creates needless binary bloat, and for profilers (ex: pprof) and other tools that capture data files based on function names, the long names can result in much bigger data files.
More importantly however if you have a package with very long paths, and you import a large struct type from that package and instantiate a generic based on that, you can get absurdly long function names.
What did you expect to see?
Ideally it would be better to have generic functions names that are proportional in size to the length of their qualified type parameters (e.g. "os/exec.Cmd") as opposed to O(N * P) where N is the number of struct fields in the type param and P is the length of the import path of the type's package.
The text was updated successfully, but these errors were encountered: