mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
f570b54cc0
commit
08816cb8d7
8 changed files with 194 additions and 177 deletions
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue