diff options
Diffstat (limited to 'libgo/go/runtime/pprof/pprof.go')
-rw-r--r-- | libgo/go/runtime/pprof/pprof.go | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go index a8e78e0ea75..42f04f320a7 100644 --- a/libgo/go/runtime/pprof/pprof.go +++ b/libgo/go/runtime/pprof/pprof.go @@ -110,6 +110,44 @@ func WriteHeapProfile(w io.Writer) error { return b.Flush() } +// WriteThreadProfile writes a pprof-formatted thread creation profile to w. +// If a write to w returns an error, WriteThreadProfile returns that error. +// Otherwise, WriteThreadProfile returns nil. +func WriteThreadProfile(w io.Writer) error { + // Find out how many records there are (ThreadProfile(nil)), + // allocate that many records, and get the data. + // There's a race—more records (threads) might be added between + // the two calls—so allocate a few extra records for safety + // and also try again if we're very unlucky. + // The loop should only execute one iteration in the common case. + var p []runtime.ThreadProfileRecord + n, ok := runtime.ThreadProfile(nil) + for { + // Allocate room for a slightly bigger profile, + // in case a few more entries have been added + // since the call to ThreadProfile. + p = make([]runtime.ThreadProfileRecord, n+10) + n, ok = runtime.ThreadProfile(p) + if ok { + p = p[0:n] + break + } + // Profile grew; try again. + } + + b := bufio.NewWriter(w) + fmt.Fprintf(b, "thread creation profile: %d threads\n", n) + for i := range p { + r := &p[i] + fmt.Fprintf(b, "@") + for _, pc := range r.Stack() { + fmt.Fprintf(b, " %#x", pc) + } + fmt.Fprintf(b, "\n") + } + return b.Flush() +} + var cpu struct { sync.Mutex profiling bool |