aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/trace/pprof.go
diff options
context:
space:
mode:
authorPeter Weinberger <pjw@google.com>2018-10-29 10:18:05 -0400
committerPeter Weinberger <pjw@google.com>2018-10-30 16:43:38 +0000
commit08816cb8d7ed16b9c804587ff02c1ad1c3af6cd5 (patch)
tree1951b6cd86b05ed0faa4dfc99e17592997b661f9 /src/cmd/trace/pprof.go
parentf570b54cc02ffeb82e35e72fc818916e8b896c67 (diff)
downloadgo-08816cb8d7ed16b9c804587ff02c1ad1c3af6cd5.tar.xz
cmd/trace: use new traceparser to parse the raw trace files
Change-Id: I8b224ae48a2f8acd5a64c9ff283e97821479a9a8 Reviewed-on: https://go-review.googlesource.com/c/145457 Run-TryBot: Peter Weinberger <pjw@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Diffstat (limited to 'src/cmd/trace/pprof.go')
-rw-r--r--src/cmd/trace/pprof.go64
1 files changed, 38 insertions, 26 deletions
diff --git a/src/cmd/trace/pprof.go b/src/cmd/trace/pprof.go
index 3389d2799b..cf74fe56ae 100644
--- a/src/cmd/trace/pprof.go
+++ b/src/cmd/trace/pprof.go
@@ -9,7 +9,6 @@ package main
import (
"bufio"
"fmt"
- "internal/trace"
"io"
"io/ioutil"
"net/http"
@@ -21,6 +20,8 @@ import (
"strconv"
"time"
+ trace "internal/traceparser"
+
"github.com/google/pprof/profile"
)
@@ -60,22 +61,22 @@ type interval struct {
begin, end int64 // nanoseconds.
}
-func pprofByGoroutine(compute func(io.Writer, map[uint64][]interval, []*trace.Event) error) func(w io.Writer, r *http.Request) error {
+func pprofByGoroutine(compute func(io.Writer, map[uint64][]interval, *trace.Parsed) error) func(w io.Writer, r *http.Request) error {
return func(w io.Writer, r *http.Request) error {
id := r.FormValue("id")
- events, err := parseEvents()
+ res, err := parseTrace()
if err != nil {
return err
}
- gToIntervals, err := pprofMatchingGoroutines(id, events)
+ gToIntervals, err := pprofMatchingGoroutines(id, res)
if err != nil {
return err
}
- return compute(w, gToIntervals, events)
+ return compute(w, gToIntervals, res)
}
}
-func pprofByRegion(compute func(io.Writer, map[uint64][]interval, []*trace.Event) error) func(w io.Writer, r *http.Request) error {
+func pprofByRegion(compute func(io.Writer, map[uint64][]interval, *trace.Parsed) error) func(w io.Writer, r *http.Request) error {
return func(w io.Writer, r *http.Request) error {
filter, err := newRegionFilter(r)
if err != nil {
@@ -85,7 +86,7 @@ func pprofByRegion(compute func(io.Writer, map[uint64][]interval, []*trace.Event
if err != nil {
return err
}
- events, _ := parseEvents()
+ events, _ := parseTrace()
return compute(w, gToIntervals, events)
}
@@ -94,7 +95,7 @@ func pprofByRegion(compute func(io.Writer, map[uint64][]interval, []*trace.Event
// pprofMatchingGoroutines parses the goroutine type id string (i.e. pc)
// and returns the ids of goroutines of the matching type and its interval.
// If the id string is empty, returns nil without an error.
-func pprofMatchingGoroutines(id string, events []*trace.Event) (map[uint64][]interval, error) {
+func pprofMatchingGoroutines(id string, p *trace.Parsed) (map[uint64][]interval, error) {
if id == "" {
return nil, nil
}
@@ -102,7 +103,7 @@ func pprofMatchingGoroutines(id string, events []*trace.Event) (map[uint64][]int
if err != nil {
return nil, fmt.Errorf("invalid goroutine type: %v", id)
}
- analyzeGoroutines(events)
+ analyzeGoroutines(p)
var res map[uint64][]interval
for _, g := range gs {
if g.PC != pc {
@@ -171,17 +172,25 @@ func pprofMatchingRegions(filter *regionFilter) (map[uint64][]interval, error) {
return gToIntervals, nil
}
+func stklen(p *trace.Parsed, ev *trace.Event) int {
+ if ev.StkID == 0 {
+ return 0
+ }
+ return len(p.Stacks[ev.StkID])
+}
+
// computePprofIO generates IO pprof-like profile (time spent in IO wait, currently only network blocking event).
-func computePprofIO(w io.Writer, gToIntervals map[uint64][]interval, events []*trace.Event) error {
- prof := make(map[uint64]Record)
+func computePprofIO(w io.Writer, gToIntervals map[uint64][]interval, res *trace.Parsed) error {
+ events := res.Events
+ prof := make(map[uint32]Record)
for _, ev := range events {
- if ev.Type != trace.EvGoBlockNet || ev.Link == nil || ev.StkID == 0 || len(ev.Stk) == 0 {
+ if ev.Type != trace.EvGoBlockNet || ev.Link == nil || ev.StkID == 0 || stklen(res, ev) == 0 {
continue
}
overlapping := pprofOverlappingDuration(gToIntervals, ev)
if overlapping > 0 {
rec := prof[ev.StkID]
- rec.stk = ev.Stk
+ rec.stk = res.Stacks[ev.StkID]
rec.n++
rec.time += overlapping.Nanoseconds()
prof[ev.StkID] = rec
@@ -191,8 +200,9 @@ func computePprofIO(w io.Writer, gToIntervals map[uint64][]interval, events []*t
}
// computePprofBlock generates blocking pprof-like profile (time spent blocked on synchronization primitives).
-func computePprofBlock(w io.Writer, gToIntervals map[uint64][]interval, events []*trace.Event) error {
- prof := make(map[uint64]Record)
+func computePprofBlock(w io.Writer, gToIntervals map[uint64][]interval, res *trace.Parsed) error {
+ events := res.Events
+ prof := make(map[uint32]Record)
for _, ev := range events {
switch ev.Type {
case trace.EvGoBlockSend, trace.EvGoBlockRecv, trace.EvGoBlockSelect,
@@ -203,13 +213,13 @@ func computePprofBlock(w io.Writer, gToIntervals map[uint64][]interval, events [
default:
continue
}
- if ev.Link == nil || ev.StkID == 0 || len(ev.Stk) == 0 {
+ if ev.Link == nil || ev.StkID == 0 || stklen(res, ev) == 0 {
continue
}
overlapping := pprofOverlappingDuration(gToIntervals, ev)
if overlapping > 0 {
rec := prof[ev.StkID]
- rec.stk = ev.Stk
+ rec.stk = res.Stacks[ev.StkID]
rec.n++
rec.time += overlapping.Nanoseconds()
prof[ev.StkID] = rec
@@ -219,16 +229,17 @@ func computePprofBlock(w io.Writer, gToIntervals map[uint64][]interval, events [
}
// computePprofSyscall generates syscall pprof-like profile (time spent blocked in syscalls).
-func computePprofSyscall(w io.Writer, gToIntervals map[uint64][]interval, events []*trace.Event) error {
- prof := make(map[uint64]Record)
+func computePprofSyscall(w io.Writer, gToIntervals map[uint64][]interval, res *trace.Parsed) error {
+ events := res.Events
+ prof := make(map[uint32]Record)
for _, ev := range events {
- if ev.Type != trace.EvGoSysCall || ev.Link == nil || ev.StkID == 0 || len(ev.Stk) == 0 {
+ if ev.Type != trace.EvGoSysCall || ev.Link == nil || ev.StkID == 0 || stklen(res, ev) == 0 {
continue
}
overlapping := pprofOverlappingDuration(gToIntervals, ev)
if overlapping > 0 {
rec := prof[ev.StkID]
- rec.stk = ev.Stk
+ rec.stk = res.Stacks[ev.StkID]
rec.n++
rec.time += overlapping.Nanoseconds()
prof[ev.StkID] = rec
@@ -239,17 +250,18 @@ func computePprofSyscall(w io.Writer, gToIntervals map[uint64][]interval, events
// computePprofSched generates scheduler latency pprof-like profile
// (time between a goroutine become runnable and actually scheduled for execution).
-func computePprofSched(w io.Writer, gToIntervals map[uint64][]interval, events []*trace.Event) error {
- prof := make(map[uint64]Record)
+func computePprofSched(w io.Writer, gToIntervals map[uint64][]interval, res *trace.Parsed) error {
+ events := res.Events
+ prof := make(map[uint32]Record)
for _, ev := range events {
if (ev.Type != trace.EvGoUnblock && ev.Type != trace.EvGoCreate) ||
- ev.Link == nil || ev.StkID == 0 || len(ev.Stk) == 0 {
+ ev.Link == nil || ev.StkID == 0 || stklen(res, ev) == 0 {
continue
}
overlapping := pprofOverlappingDuration(gToIntervals, ev)
if overlapping > 0 {
rec := prof[ev.StkID]
- rec.stk = ev.Stk
+ rec.stk = res.Stacks[ev.StkID]
rec.n++
rec.time += overlapping.Nanoseconds()
prof[ev.StkID] = rec
@@ -327,7 +339,7 @@ func serveSVGProfile(prof func(w io.Writer, r *http.Request) error) http.Handler
}
}
-func buildProfile(prof map[uint64]Record) *profile.Profile {
+func buildProfile(prof map[uint32]Record) *profile.Profile {
p := &profile.Profile{
PeriodType: &profile.ValueType{Type: "trace", Unit: "count"},
Period: 1,