Skip to content
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

runtime/pprof: unexpectedly seeing full struct definitions in function names for generics functions #65147

Closed
S-YOU opened this issue Jan 18, 2024 · 6 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@S-YOU
Copy link

S-YOU commented Jan 18, 2024

Go version

go1.20.6 linux/amd64

Output of go env in your module/workspace:

GO111MODULE='auto'
GOARCH='amd64'
GOBIN=''
GOCACHE='<HOME>/.cache/go-build'
GOENV='<HOME>/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS='-mod=readonly'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='<HOME>/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='<HOME>/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/go'
GOSUMDB='off'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.6'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='<HOME>/go/src/r/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 -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1751412201=/tmp/go-build -gno-record-gcc-switches'

What did you do?

When I profile with pprof, func name output is too large for struct types.

Might related to this fix with 1.21.6

What did you see happen?

When you pass large struct as Type to generics functions, pprof show all if its definition like this.
image

What did you expect to see?

Only struct Name or with package name for Types passed to generics function, instead of full definition on pprof output.

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Jan 18, 2024
@mauri870 mauri870 added WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Jan 18, 2024
@mauri870
Copy link
Member

mauri870 commented Jan 18, 2024

I expected this to be fixed with Go 1.21.6. Are you trying to open a pprof captured with an old version of Go?

@prattmic
Copy link
Member

I don't think this is related to #64528 (the bug fixed in 1.21.6). That is about the profile containing an incorrect symbol name.

AFAICT, this issue is simply about the giant name in the profile. That name is the actual symbol name, for better or worse. The CL on #65030 (included in 1.22) uses a hashed name for these giant names to keep them small. That should make the pprof graph look less absurd, but at the expensive that it will no longer be possible to tell what the type parameters are.

@S-YOU
Copy link
Author

S-YOU commented Jan 19, 2024

I expected this to be fixed with Go 1.21.6. Are you trying to open a pprof captured with an old version of Go?

Go verison is 1.21.6 as I added go env result or is there chance that go tool pprof command calling some other binaries which is old?

@S-YOU
Copy link
Author

S-YOU commented Jan 19, 2024

That should make the pprof graph look less absurd, but at the expensive that it will no longer be possible to tell what the type parameters are.

I could undstertand that, but is there a need to treat any struct like anonymous and show its body instead? The one I am passing is the struct name itself, so it should have the name like package.Struct.

EDIT: I took a look at #65030, but it seems like a workaround for visual. Is that also mean Go does not even hold the name of the type (struct's full name) passed in generics functions?

@prattmic
Copy link
Member

I could undstertand that, but is there a need to treat any struct like anonymous and show its body instead? The one I am passing is the struct name itself, so it should have the name like package.Struct.

The Go toolchain uses a dictionary-based generics implementation. That doc has complete details, but the critical aspect is that the compiler does not create a unique function instantiation for every distinct type argument. A single instantiation is shared by all types that have the same shape.

You can see an example of this with this program:

package main

import (
        "fmt"
)

//go:noinline
func Print[T any](v T) {
        fmt.Println(v)
}

type A struct {
        Foo int
}

type B struct {
        Foo int
}

type C A

func main() {
        var (
                a A
                b B
                c C
        )
        Print(a)
        Print(b)
        Print(c)
}

If you look at the disassembly, you'll see that even though Print is instantiated with three different types (A, B, and C), there is only a single symbol that all three share: main.Print[go.shape.struct { Foo int }].

@S-YOU
Copy link
Author

S-YOU commented Jan 20, 2024

Thanks for the the detail explanations, seems like even I write like Print[A](a), output are the same.
Closing for now.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. 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