diff options
Diffstat (limited to 'libgo/go/runtime/pprof/pprof.go')
-rw-r--r-- | libgo/go/runtime/pprof/pprof.go | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go index 183881c..52df44a 100644 --- a/libgo/go/runtime/pprof/pprof.go +++ b/libgo/go/runtime/pprof/pprof.go @@ -313,9 +313,11 @@ func (p *Profile) Remove(value interface{}) { // Otherwise, WriteTo returns nil. // // The debug parameter enables additional output. -// Passing debug=0 prints only the hexadecimal addresses that pprof needs. -// Passing debug=1 adds comments translating addresses to function names -// and line numbers, so that a programmer can read the profile without tools. +// Passing debug=0 writes the gzip-compressed protocol buffer described +// in https://github.com/google/pprof/tree/master/proto#overview. +// Passing debug=1 writes the legacy text format with comments +// translating addresses to function names and line numbers, so that a +// programmer can read the profile without tools. // // The predefined profiles may assign meaning to other debug values; // for example, when printing the "goroutine" profile, debug=2 means to @@ -355,6 +357,7 @@ type stackProfile [][]uintptr func (x stackProfile) Len() int { return len(x) } func (x stackProfile) Stack(i int) []uintptr { return x[i] } +func (x stackProfile) Label(i int) *labelMap { return nil } // A countProfile is a set of stack traces to be printed as counts // grouped by stack trace. There are multiple implementations: @@ -363,6 +366,7 @@ func (x stackProfile) Stack(i int) []uintptr { return x[i] } type countProfile interface { Len() int Stack(i int) []uintptr + Label(i int) *labelMap } // printCountCycleProfile outputs block profile records (for block or mutex profiles) @@ -400,12 +404,16 @@ func printCountCycleProfile(w io.Writer, countName, cycleName string, scaler fun func printCountProfile(w io.Writer, debug int, name string, p countProfile) error { // Build count of each stack. var buf bytes.Buffer - key := func(stk []uintptr) string { + key := func(stk []uintptr, lbls *labelMap) string { buf.Reset() fmt.Fprintf(&buf, "@") for _, pc := range stk { fmt.Fprintf(&buf, " %#x", pc) } + if lbls != nil { + buf.WriteString("\n# labels: ") + buf.WriteString(lbls.String()) + } return buf.String() } count := map[string]int{} @@ -413,7 +421,7 @@ func printCountProfile(w io.Writer, debug int, name string, p countProfile) erro var keys []string n := p.Len() for i := 0; i < n; i++ { - k := key(p.Stack(i)) + k := key(p.Stack(i), p.Label(i)) if count[k] == 0 { index[k] = i keys = append(keys, k) @@ -447,7 +455,16 @@ func printCountProfile(w io.Writer, debug int, name string, p countProfile) erro // For count profiles, all stack addresses are // return PCs, which is what appendLocsForStack expects. locs = b.appendLocsForStack(locs[:0], p.Stack(index[k])) - b.pbSample(values, locs, nil) + idx := index[k] + var labels func() + if p.Label(idx) != nil { + labels = func() { + for k, v := range *p.Label(idx) { + b.pbLabel(tagSample_Label, k, v, 0) + } + } + } + b.pbSample(values, locs, labels) } b.build() return nil @@ -642,6 +659,9 @@ func writeHeapInternal(w io.Writer, debug int, defaultSampleType string) error { fmt.Fprintf(w, "# GCCPUFraction = %v\n", s.GCCPUFraction) fmt.Fprintf(w, "# DebugGC = %v\n", s.DebugGC) + // Also flush out MaxRSS on supported platforms. + addMaxRSS(w) + tw.Flush() return b.Flush() } @@ -654,7 +674,12 @@ func countThreadCreate() int { // writeThreadCreate writes the current runtime ThreadCreateProfile to w. func writeThreadCreate(w io.Writer, debug int) error { - return writeRuntimeProfile(w, debug, "threadcreate", runtime.ThreadCreateProfile) + // Until https://golang.org/issues/6104 is addressed, wrap + // ThreadCreateProfile because there's no point in tracking labels when we + // don't get any stack-traces. + return writeRuntimeProfile(w, debug, "threadcreate", func(p []runtime.StackRecord, _ []unsafe.Pointer) (n int, ok bool) { + return runtime.ThreadCreateProfile(p) + }) } // countGoroutine returns the number of goroutines. @@ -662,12 +687,15 @@ func countGoroutine() int { return runtime.NumGoroutine() } +// runtime_goroutineProfileWithLabels is defined in runtime/mprof.go +func runtime_goroutineProfileWithLabels(p []runtime.StackRecord, labels []unsafe.Pointer) (n int, ok bool) + // writeGoroutine writes the current runtime GoroutineProfile to w. func writeGoroutine(w io.Writer, debug int) error { if debug >= 2 { return writeGoroutineStacks(w) } - return writeRuntimeProfile(w, debug, "goroutine", runtime.GoroutineProfile) + return writeRuntimeProfile(w, debug, "goroutine", runtime_goroutineProfileWithLabels) } func writeGoroutineStacks(w io.Writer) error { @@ -691,7 +719,7 @@ func writeGoroutineStacks(w io.Writer) error { return err } -func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runtime.StackRecord) (int, bool)) error { +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. // There's a race—more records might be added between @@ -699,13 +727,15 @@ func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runti // and also try again if we're very unlucky. // The loop should only execute one iteration in the common case. var p []runtime.StackRecord - n, ok := fetch(nil) + var labels []unsafe.Pointer + n, ok := fetch(nil, 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.StackRecord, n+10) - n, ok = fetch(p) + labels = make([]unsafe.Pointer, n+10) + n, ok = fetch(p, labels) if ok { p = p[0:n] break @@ -713,13 +743,17 @@ func writeRuntimeProfile(w io.Writer, debug int, name string, fetch func([]runti // Profile grew; try again. } - return printCountProfile(w, debug, name, runtimeProfile(p)) + return printCountProfile(w, debug, name, &runtimeProfile{p, labels}) } -type runtimeProfile []runtime.StackRecord +type runtimeProfile struct { + stk []runtime.StackRecord + labels []unsafe.Pointer +} -func (p runtimeProfile) Len() int { return len(p) } -func (p runtimeProfile) Stack(i int) []uintptr { return p[i].Stack() } +func (p *runtimeProfile) Len() int { return len(p.stk) } +func (p *runtimeProfile) Stack(i int) []uintptr { return p.stk[i].Stack() } +func (p *runtimeProfile) Label(i int) *labelMap { return (*labelMap)(p.labels[i]) } var cpu struct { sync.Mutex |