mirror of
https://github.com/golang/go
synced 2024-10-04 21:11:22 -06:00
cmd/trace: generate new pprof profiles
Generate new protobuf pprof profiles with embed symbol info. This makes program binary unnecessary. Change-Id: Ie628439c13c5e34199782031138102c83ea50621 Reviewed-on: https://go-review.googlesource.com/21873 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com> Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
This commit is contained in:
parent
d32229b3b1
commit
f71a13da93
@ -8,6 +8,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"cmd/internal/pprof/profile"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/trace"
|
"internal/trace"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -133,34 +134,79 @@ func serveSVGProfile(w http.ResponseWriter, r *http.Request, prof map[uint64]Rec
|
|||||||
http.Error(w, fmt.Sprintf("failed to create temp file: %v", err), http.StatusInternalServerError)
|
http.Error(w, fmt.Sprintf("failed to create temp file: %v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.Remove(blockf.Name())
|
defer func() {
|
||||||
|
blockf.Close()
|
||||||
|
os.Remove(blockf.Name())
|
||||||
|
}()
|
||||||
blockb := bufio.NewWriter(blockf)
|
blockb := bufio.NewWriter(blockf)
|
||||||
fmt.Fprintf(blockb, "--- contention:\ncycles/second=1000000000\n")
|
if err := buildProfile(prof).Write(blockb); err != nil {
|
||||||
for _, rec := range prof {
|
http.Error(w, fmt.Sprintf("failed to write profile: %v", err), http.StatusInternalServerError)
|
||||||
fmt.Fprintf(blockb, "%v %v @", rec.time, rec.n)
|
return
|
||||||
for _, f := range rec.stk {
|
|
||||||
fmt.Fprintf(blockb, " 0x%x", f.PC)
|
|
||||||
}
|
}
|
||||||
fmt.Fprintf(blockb, "\n")
|
if err := blockb.Flush(); err != nil {
|
||||||
}
|
|
||||||
err = blockb.Flush()
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("failed to flush temp file: %v", err), http.StatusInternalServerError)
|
http.Error(w, fmt.Sprintf("failed to flush temp file: %v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = blockf.Close()
|
if err := blockf.Close(); err != nil {
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("failed to close temp file: %v", err), http.StatusInternalServerError)
|
http.Error(w, fmt.Sprintf("failed to close temp file: %v", err), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
svgFilename := blockf.Name() + ".svg"
|
svgFilename := blockf.Name() + ".svg"
|
||||||
_, err = exec.Command("go", "tool", "pprof", "-svg", "-output", svgFilename, programBinary, blockf.Name()).CombinedOutput()
|
if output, err := exec.Command("go", "tool", "pprof", "-svg", "-output", svgFilename, blockf.Name()).CombinedOutput(); err != nil {
|
||||||
if err != nil {
|
http.Error(w, fmt.Sprintf("failed to execute go tool pprof: %v\n%s", err, output), http.StatusInternalServerError)
|
||||||
http.Error(w, fmt.Sprintf("failed to execute go tool pprof: %v", err), http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer os.Remove(svgFilename)
|
defer os.Remove(svgFilename)
|
||||||
w.Header().Set("Content-Type", "image/svg+xml")
|
w.Header().Set("Content-Type", "image/svg+xml")
|
||||||
http.ServeFile(w, r, svgFilename)
|
http.ServeFile(w, r, svgFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildProfile(prof map[uint64]Record) *profile.Profile {
|
||||||
|
p := &profile.Profile{
|
||||||
|
PeriodType: &profile.ValueType{Type: "trace", Unit: "count"},
|
||||||
|
Period: 1,
|
||||||
|
SampleType: []*profile.ValueType{
|
||||||
|
{Type: "contentions", Unit: "count"},
|
||||||
|
{Type: "delay", Unit: "nanoseconds"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
locs := make(map[uint64]*profile.Location)
|
||||||
|
funcs := make(map[string]*profile.Function)
|
||||||
|
for _, rec := range prof {
|
||||||
|
var sloc []*profile.Location
|
||||||
|
for _, frame := range rec.stk {
|
||||||
|
loc := locs[frame.PC]
|
||||||
|
if loc == nil {
|
||||||
|
fn := funcs[frame.File+frame.Fn]
|
||||||
|
if fn == nil {
|
||||||
|
fn = &profile.Function{
|
||||||
|
ID: uint64(len(p.Function) + 1),
|
||||||
|
Name: frame.Fn,
|
||||||
|
SystemName: frame.Fn,
|
||||||
|
Filename: frame.File,
|
||||||
|
}
|
||||||
|
p.Function = append(p.Function, fn)
|
||||||
|
funcs[frame.File+frame.Fn] = fn
|
||||||
|
}
|
||||||
|
loc = &profile.Location{
|
||||||
|
ID: uint64(len(p.Location) + 1),
|
||||||
|
Address: frame.PC,
|
||||||
|
Line: []profile.Line{
|
||||||
|
profile.Line{
|
||||||
|
Function: fn,
|
||||||
|
Line: int64(frame.Line),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p.Location = append(p.Location, loc)
|
||||||
|
locs[frame.PC] = loc
|
||||||
|
}
|
||||||
|
sloc = append(sloc, loc)
|
||||||
|
}
|
||||||
|
p.Sample = append(p.Sample, &profile.Sample{
|
||||||
|
Value: []int64{int64(rec.n), rec.time},
|
||||||
|
Location: sloc,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user