From 0ce94d79bc7dda4c6f86c6ac13bf0bdd20d0ffdf Mon Sep 17 00:00:00 2001 From: David Chase Date: Tue, 24 Oct 2023 13:57:35 -0400 Subject: [PATCH] cmd/compile: modify -memprofile flag for multiple profiles in a directory This permits collection of multiple profiles in a build (instead of just the last compilation). If a -memprofile specifies an existing directory instead of a file, it will create ".mprof" in that directory. The PathEscaped package names are ugly, but this puts all the files in a single directory with no risk of name clashs, which simplies the usual case for using these files, which is something like ``` go tool pprof profiles/*.mprof ``` Creating a directory tree mimicking the package structure requires something along the lines of ``` go tool pprof `find profiles -name "*.mprof" -print` ``` In addition, this turns off "legacy format" because that is only useful for a benchcompile, which does not use this new feature (and people actually interested in memory profiles probably prefer the new ones). Change-Id: Ic1d9da53af22ecdda17663e0d4bce7cdbcb54527 Reviewed-on: https://go-review.googlesource.com/c/go/+/539316 Run-TryBot: David Chase Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky TryBot-Result: Gopher Robot Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/util.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/gc/util.go b/src/cmd/compile/internal/gc/util.go index dcac0ce79a..5615d60b57 100644 --- a/src/cmd/compile/internal/gc/util.go +++ b/src/cmd/compile/internal/gc/util.go @@ -5,7 +5,9 @@ package gc import ( + "net/url" "os" + "path/filepath" "runtime" "runtime/pprof" tracepkg "runtime/trace" @@ -28,18 +30,30 @@ func startProfile() { if base.Flag.MemProfileRate != 0 { runtime.MemProfileRate = base.Flag.MemProfileRate } - f, err := os.Create(base.Flag.MemProfile) + const ( + gzipFormat = 0 + textFormat = 1 + ) + // compilebench parses the memory profile to extract memstats, + // which are only written in the legacy (text) pprof format. + // See golang.org/issue/18641 and runtime/pprof/pprof.go:writeHeap. + // gzipFormat is what most people want, otherwise + var format = textFormat + fn := base.Flag.MemProfile + if fi, statErr := os.Stat(fn); statErr == nil && fi.IsDir() { + fn = filepath.Join(fn, url.PathEscape(base.Ctxt.Pkgpath)+".mprof") + format = gzipFormat + } + + f, err := os.Create(fn) + if err != nil { base.Fatalf("%v", err) } base.AtExit(func() { // Profile all outstanding allocations. runtime.GC() - // compilebench parses the memory profile to extract memstats, - // which are only written in the legacy pprof format. - // See golang.org/issue/18641 and runtime/pprof/pprof.go:writeHeap. - const writeLegacyFormat = 1 - if err := pprof.Lookup("heap").WriteTo(f, writeLegacyFormat); err != nil { + if err := pprof.Lookup("heap").WriteTo(f, format); err != nil { base.Fatalf("%v", err) } })