diff options
| author | Michael Pratt <mpratt@google.com> | 2024-01-30 11:01:05 -0500 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-01-30 16:34:07 +0000 |
| commit | 65f056d07ad1db7dd4fb23c4d35cf7b8bd0d6008 (patch) | |
| tree | b875be427cd4c49c3e8f9cfe2a0e5af7d5091eaa /src | |
| parent | b89ad464510e643c23df28bc5c181ad0a16773bf (diff) | |
| download | go-65f056d07ad1db7dd4fb23c4d35cf7b8bd0d6008.tar.xz | |
runtime: avoid new linkname for goroutine profiles
CL 464349 added a new linkname to provide gcount to runtime/pprof to
avoid a STW when estimating the goroutine profile allocation size.
However, adding a linkname here isn't necessary for a few reasons:
1. We already export gcount via NumGoroutines. I completely forgot about
this during review.
2. aktau suggested that goroutineProfileWithLabelsConcurrent return
gcount as a fast path estimate when the input is empty.
The second point keeps the code cleaner overall, so I've done that.
For #54014.
Change-Id: I6cb0811a769c805e269b55774cdd43509854078e
Reviewed-on: https://go-review.googlesource.com/c/go/+/559515
Auto-Submit: Michael Pratt <mpratt@google.com>
Auto-Submit: Nicolas Hillegeer <aktau@google.com>
Reviewed-by: Nicolas Hillegeer <aktau@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/runtime/mprof.go | 13 | ||||
| -rw-r--r-- | src/runtime/pprof/pprof.go | 10 |
2 files changed, 9 insertions, 14 deletions
diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index 09cea65bd9..c232b15424 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -1131,12 +1131,15 @@ func (p *goroutineProfileStateHolder) CompareAndSwap(old, new goroutineProfileSt return (*atomic.Uint32)(p).CompareAndSwap(uint32(old), uint32(new)) } -//go:linkname runtime_gcount runtime/pprof.runtime_gcount -func runtime_gcount() int { - return int(gcount()) -} - func goroutineProfileWithLabelsConcurrent(p []StackRecord, labels []unsafe.Pointer) (n int, ok bool) { + if len(p) == 0 { + // An empty slice is obviously too small. Return a rough + // allocation estimate without bothering to STW. As long as + // this is close, then we'll only need to STW once (on the next + // call). + return int(gcount()), false + } + semacquire(&goroutineProfile.sema) ourg := getg() diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go index 79ca11c6b4..a8422181cc 100644 --- a/src/runtime/pprof/pprof.go +++ b/src/runtime/pprof/pprof.go @@ -755,9 +755,6 @@ func writeGoroutineStacks(w io.Writer) error { return err } -// runtime_gcount is defined in runtime/mprof.go -func runtime_gcount() (n int) - func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runtime.StackRecord, []unsafe.Pointer) (int, bool)) error { // Find out how many records there are (fetch(nil)), // allocate that many records, and get the data. @@ -767,12 +764,7 @@ func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runti // The loop should only execute one iteration in the common case. var p []runtime.StackRecord var labels []unsafe.Pointer - var n, ok = 0, false - if name == "goroutine" { - n = runtime_gcount() - } else { - n, ok = fetch(nil, nil) - } + n, ok := fetch(nil, nil) for { // Allocate room for a slightly bigger profile, |
