]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: avoid new linkname for goroutine profiles
authorMichael Pratt <mpratt@google.com>
Tue, 30 Jan 2024 16:01:05 +0000 (11:01 -0500)
committerGopher Robot <gobot@golang.org>
Tue, 30 Jan 2024 16:34:07 +0000 (16:34 +0000)
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>

src/runtime/mprof.go
src/runtime/pprof/pprof.go

index 09cea65bd917338a98a2ab69517ee1d3c3396bc5..c232b15424e78029fb66df57378d3fad67ef152d 100644 (file)
@@ -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()
index 79ca11c6b4c7c168f9f5da1c6ba44d78766a3379..a8422181cca4f72bfc8a6726e5a1b0fe5cb8c980 100644 (file)
@@ -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,