aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/pprof/pprof.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/pprof/pprof.go')
-rw-r--r--libgo/go/runtime/pprof/pprof.go64
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