diff options
| author | Peter Weinberger <pjw@google.com> | 2018-10-29 10:18:05 -0400 |
|---|---|---|
| committer | Peter Weinberger <pjw@google.com> | 2018-10-30 16:43:38 +0000 |
| commit | 08816cb8d7ed16b9c804587ff02c1ad1c3af6cd5 (patch) | |
| tree | 1951b6cd86b05ed0faa4dfc99e17592997b661f9 /src/cmd/trace/pprof.go | |
| parent | f570b54cc02ffeb82e35e72fc818916e8b896c67 (diff) | |
| download | go-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.go | 64 |
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, |
