mirror of
https://github.com/golang/go
synced 2024-10-14 11:53:56 +00:00
cmd/vendor: update github.com/google/pprof
Brings in the latest github.com/google/pprof. Fixes #67626 Change-Id: Id8faef20f0a9bf81dd117110bf540aca852db6be Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest Reviewed-on: https://go-review.googlesource.com/c/go/+/588655 Reviewed-by: Carlos Amedee <carlos@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
This commit is contained in:
parent
00b8071a12
commit
9b43bfbc51
|
@ -3,7 +3,7 @@ module cmd
|
|||
go 1.23
|
||||
|
||||
require (
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba
|
||||
golang.org/x/arch v0.7.0
|
||||
golang.org/x/build v0.0.0-20240222153247-cf4ed81bb19f
|
||||
golang.org/x/mod v0.17.1-0.20240514174713-c0bdc7bd01c9
|
||||
|
@ -15,7 +15,7 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab // indirect
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
rsc.io/markdown v0.0.0-20240117044121-669d2fdf1650 // indirect
|
||||
)
|
||||
|
|
|
@ -1,25 +1,9 @@
|
|||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89 h1:aPflPkRFkVwbW6dmcVqfgwp1i+UWGFH6VgR1Jim5Ygc=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.9.2 h1:dKtNz4kApb06KuSXoTQIyUC2TrA0fhGDwNZf3bcgfKw=
|
||||
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g=
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465 h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
|
||||
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
||||
|
|
2
src/cmd/vendor/github.com/google/pprof/driver/driver.go
generated
vendored
2
src/cmd/vendor/github.com/google/pprof/driver/driver.go
generated
vendored
|
@ -202,7 +202,7 @@ type Sym struct {
|
|||
|
||||
// A UI manages user interactions.
|
||||
type UI interface {
|
||||
// Read returns a line of text (a command) read from the user.
|
||||
// ReadLine returns a line of text (a command) read from the user.
|
||||
// prompt is printed before reading the command.
|
||||
ReadLine(prompt string) (string, error)
|
||||
|
||||
|
|
6
src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go
generated
vendored
6
src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go
generated
vendored
|
@ -433,10 +433,8 @@ func (b *binrep) openELF(name string, start, limit, offset uint64, relocationSym
|
|||
defer ef.Close()
|
||||
|
||||
buildID := ""
|
||||
if f, err := os.Open(name); err == nil {
|
||||
if id, err := elfexec.GetBuildID(f); err == nil {
|
||||
buildID = fmt.Sprintf("%x", id)
|
||||
}
|
||||
if id, err := elfexec.GetBuildID(ef); err == nil {
|
||||
buildID = fmt.Sprintf("%x", id)
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
22
src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go
generated
vendored
22
src/cmd/vendor/github.com/google/pprof/internal/driver/driver.go
generated
vendored
|
@ -20,6 +20,7 @@ package driver
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
@ -118,7 +119,14 @@ func generateReport(p *profile.Profile, cmd []string, cfg config, o *plugin.Opti
|
|||
|
||||
// Generate the report.
|
||||
dst := new(bytes.Buffer)
|
||||
if err := report.Generate(dst, rpt, o.Obj); err != nil {
|
||||
switch rpt.OutputFormat() {
|
||||
case report.WebList:
|
||||
// We need template expansion, so generate here instead of in report.
|
||||
err = printWebList(dst, rpt, o.Obj)
|
||||
default:
|
||||
err = report.Generate(dst, rpt, o.Obj)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
src := dst
|
||||
|
@ -155,6 +163,18 @@ func generateReport(p *profile.Profile, cmd []string, cfg config, o *plugin.Opti
|
|||
return out.Close()
|
||||
}
|
||||
|
||||
func printWebList(dst io.Writer, rpt *report.Report, obj plugin.ObjTool) error {
|
||||
listing, err := report.MakeWebList(rpt, obj, -1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
legend := report.ProfileLabels(rpt)
|
||||
return renderHTML(dst, "sourcelisting", rpt, nil, legend, webArgs{
|
||||
Standalone: true,
|
||||
Listing: listing,
|
||||
})
|
||||
}
|
||||
|
||||
func applyCommandOverrides(cmd string, outputFormat int, cfg config) config {
|
||||
// Some report types override the trim flag to false below. This is to make
|
||||
// sure the default heuristics of excluding insignificant nodes and edges
|
||||
|
|
2
src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go
generated
vendored
2
src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go
generated
vendored
|
@ -493,7 +493,7 @@ func fetch(source string, duration, timeout time.Duration, ui plugin.UI, tr http
|
|||
var f io.ReadCloser
|
||||
|
||||
// First determine whether the source is a file, if not, it will be treated as a URL.
|
||||
if _, openErr := os.Stat(source); openErr == nil {
|
||||
if _, err = os.Stat(source); err == nil {
|
||||
if isPerfFile(source) {
|
||||
f, err = convertPerfData(source, ui)
|
||||
} else {
|
||||
|
|
7
src/cmd/vendor/github.com/google/pprof/internal/driver/html/graph.css
generated
vendored
Normal file
7
src/cmd/vendor/github.com/google/pprof/internal/driver/html/graph.css
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
#graph {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
#graph:active {
|
||||
cursor: grabbing;
|
||||
}
|
1
src/cmd/vendor/github.com/google/pprof/internal/driver/html/graph.html
generated
vendored
1
src/cmd/vendor/github.com/google/pprof/internal/driver/html/graph.html
generated
vendored
|
@ -4,6 +4,7 @@
|
|||
<meta charset="utf-8">
|
||||
<title>{{.Title}}</title>
|
||||
{{template "css" .}}
|
||||
{{template "graph_css" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "header" .}}
|
||||
|
|
70
src/cmd/vendor/github.com/google/pprof/internal/driver/html/source.html
generated
vendored
70
src/cmd/vendor/github.com/google/pprof/internal/driver/html/source.html
generated
vendored
|
@ -3,16 +3,70 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{.Title}}</title>
|
||||
{{template "css" .}}
|
||||
{{if not .Standalone}}{{template "css" .}}{{end}}
|
||||
{{template "weblistcss" .}}
|
||||
{{template "weblistjs" .}}
|
||||
</head>
|
||||
<body>
|
||||
{{template "header" .}}
|
||||
<div id="content" class="source">
|
||||
{{.HTMLBody}}
|
||||
</div>
|
||||
{{template "script" .}}
|
||||
<script>viewer(new URL(window.location.href), null);</script>
|
||||
<body>{{"\n" -}}
|
||||
{{/* emit different header in standalone mode */ -}}
|
||||
{{if .Standalone}}{{"\n" -}}
|
||||
<div class="legend">{{"" -}}
|
||||
{{range $i, $e := .Legend -}}
|
||||
{{if $i}}<br>{{"\n"}}{{end}}{{. -}}
|
||||
{{end}}<br>Total: {{.Listing.Total -}}
|
||||
</div>{{"" -}}
|
||||
{{else -}}
|
||||
{{template "header" .}}
|
||||
<div id="content" class="source">{{"" -}}
|
||||
{{end -}}
|
||||
|
||||
{{range .Listing.Files -}}
|
||||
{{range .Funcs -}}
|
||||
<h2>{{.Name}}</h2>{{"" -}}
|
||||
<p class="filename">{{.File}}</p>{{"\n" -}}
|
||||
<pre onClick="pprof_toggle_asm(event)">{{"\n" -}}
|
||||
{{printf " Total: %10s %10s (flat, cum) %s" .Flat .Cumulative .Percent -}}
|
||||
{{range .Lines -}}{{"\n" -}}
|
||||
{{/* source line */ -}}
|
||||
<span class=line>{{printf " %6d" .Line}}</span>{{" " -}}
|
||||
<span class={{.HTMLClass}}>
|
||||
{{- printf " %10s %10s %8s %s " .Flat .Cumulative "" .SrcLine -}}
|
||||
</span>{{"" -}}
|
||||
|
||||
{{if .Instructions -}}
|
||||
{{/* instructions for this source line */ -}}
|
||||
<span class=asm>{{"" -}}
|
||||
{{range .Instructions -}}
|
||||
{{/* separate when we hit a new basic block */ -}}
|
||||
{{if .NewBlock -}}{{printf " %8s %28s\n" "" "⋮"}}{{end -}}
|
||||
|
||||
{{/* inlined calls leading to this instruction */ -}}
|
||||
{{range .InlinedCalls -}}
|
||||
{{printf " %8s %10s %10s %8s " "" "" "" "" -}}
|
||||
<span class=inlinesrc>{{.SrcLine}}</span>{{" " -}}
|
||||
<span class=unimportant>{{.FileBase}}:{{.Line}}</span>{{"\n" -}}
|
||||
{{end -}}
|
||||
|
||||
{{if not .Synthetic -}}
|
||||
{{/* disassembled instruction */ -}}
|
||||
{{printf " %8s %10s %10s %8x: %s " "" .Flat .Cumulative .Address .Disasm -}}
|
||||
<span class=unimportant>{{.FileLine}}</span>{{"\n" -}}
|
||||
{{end -}}
|
||||
{{end -}}
|
||||
</span>{{"" -}}
|
||||
{{end -}}
|
||||
{{/* end of line */ -}}
|
||||
{{end}}{{"\n" -}}
|
||||
</pre>{{"\n" -}}
|
||||
{{/* end of function */ -}}
|
||||
{{end -}}
|
||||
{{/* end of file */ -}}
|
||||
{{end -}}
|
||||
|
||||
{{if not .Standalone}}{{"\n " -}}
|
||||
</div>{{"\n" -}}
|
||||
{{template "script" .}}{{"\n" -}}
|
||||
<script>viewer(new URL(window.location.href), null);</script>{{"" -}}
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
1
src/cmd/vendor/github.com/google/pprof/internal/driver/html/stacks.html
generated
vendored
1
src/cmd/vendor/github.com/google/pprof/internal/driver/html/stacks.html
generated
vendored
|
@ -26,6 +26,7 @@
|
|||
{{template "script" .}}
|
||||
{{template "stacks_js"}}
|
||||
<script>
|
||||
pprofUnitDefs = {{.UnitDefs}};
|
||||
stackViewer({{.Stacks}}, {{.Nodes}});
|
||||
</script>
|
||||
</body>
|
||||
|
|
60
src/cmd/vendor/github.com/google/pprof/internal/driver/html/stacks.js
generated
vendored
60
src/cmd/vendor/github.com/google/pprof/internal/driver/html/stacks.js
generated
vendored
|
@ -13,23 +13,6 @@ function stackViewer(stacks, nodes) {
|
|||
const FONT_SIZE = 12;
|
||||
const MIN_FONT_SIZE = 8;
|
||||
|
||||
// Mapping from unit to a list of display scales/labels.
|
||||
// List should be ordered by increasing unit size.
|
||||
const UNITS = new Map([
|
||||
['B', [
|
||||
['B', 1],
|
||||
['kB', Math.pow(2, 10)],
|
||||
['MB', Math.pow(2, 20)],
|
||||
['GB', Math.pow(2, 30)],
|
||||
['TB', Math.pow(2, 40)],
|
||||
['PB', Math.pow(2, 50)]]],
|
||||
['s', [
|
||||
['ns', 1e-9],
|
||||
['µs', 1e-6],
|
||||
['ms', 1e-3],
|
||||
['s', 1],
|
||||
['hrs', 60*60]]]]);
|
||||
|
||||
// Fields
|
||||
let pivots = []; // Indices of currently selected data.Sources entries.
|
||||
let matches = new Set(); // Indices of sources that match search
|
||||
|
@ -570,22 +553,7 @@ function stackViewer(stacks, nodes) {
|
|||
|
||||
// unitText returns a formatted string to display for value.
|
||||
function unitText(value) {
|
||||
const sign = (value < 0) ? "-" : "";
|
||||
let v = Math.abs(value) * stacks.Scale;
|
||||
// Rescale to appropriate display unit.
|
||||
let unit = stacks.Unit;
|
||||
const list = UNITS.get(unit);
|
||||
if (list) {
|
||||
// Find first entry in list that is not too small.
|
||||
for (const [name, scale] of list) {
|
||||
if (v <= 100*scale) {
|
||||
v /= scale;
|
||||
unit = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sign + Number(v.toFixed(2)) + unit;
|
||||
return pprofUnitText(value*stacks.Scale, stacks.Unit);
|
||||
}
|
||||
|
||||
function find(name) {
|
||||
|
@ -606,3 +574,29 @@ function stackViewer(stacks, nodes) {
|
|||
return hsl;
|
||||
}
|
||||
}
|
||||
|
||||
// pprofUnitText returns a formatted string to display for value in the specified unit.
|
||||
function pprofUnitText(value, unit) {
|
||||
const sign = (value < 0) ? "-" : "";
|
||||
let v = Math.abs(value);
|
||||
// Rescale to appropriate display unit.
|
||||
let list = null;
|
||||
for (const def of pprofUnitDefs) {
|
||||
if (def.DefaultUnit.CanonicalName == unit) {
|
||||
list = def.Units;
|
||||
v *= def.DefaultUnit.Factor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (list) {
|
||||
// Stop just before entry that is too large.
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (i == list.length-1 || list[i+1].Factor > v) {
|
||||
v /= list[i].Factor;
|
||||
unit = list[i].CanonicalName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sign + Number(v.toFixed(2)) + unit;
|
||||
}
|
||||
|
|
2
src/cmd/vendor/github.com/google/pprof/internal/driver/settings.go
generated
vendored
2
src/cmd/vendor/github.com/google/pprof/internal/driver/settings.go
generated
vendored
|
@ -102,7 +102,7 @@ func configMenu(fname string, u url.URL) []configMenuEntry {
|
|||
UserConfig: (i != 0),
|
||||
}
|
||||
}
|
||||
// Mark the last matching config as currennt
|
||||
// Mark the last matching config as current
|
||||
if lastMatch >= 0 {
|
||||
result[lastMatch].Current = true
|
||||
}
|
||||
|
|
6
src/cmd/vendor/github.com/google/pprof/internal/driver/stacks.go
generated
vendored
6
src/cmd/vendor/github.com/google/pprof/internal/driver/stacks.go
generated
vendored
|
@ -19,6 +19,7 @@ import (
|
|||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"github.com/google/pprof/internal/measurement"
|
||||
"github.com/google/pprof/internal/report"
|
||||
)
|
||||
|
||||
|
@ -52,7 +53,8 @@ func (ui *webInterface) stackView(w http.ResponseWriter, req *http.Request) {
|
|||
|
||||
_, legend := report.TextItems(rpt)
|
||||
ui.render(w, req, "stacks", rpt, errList, legend, webArgs{
|
||||
Stacks: template.JS(b),
|
||||
Nodes: nodes,
|
||||
Stacks: template.JS(b),
|
||||
Nodes: nodes,
|
||||
UnitDefs: measurement.UnitTypes,
|
||||
})
|
||||
}
|
||||
|
|
20
src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go
generated
vendored
20
src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go
generated
vendored
|
@ -19,8 +19,27 @@ import (
|
|||
"fmt"
|
||||
"html/template"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/google/pprof/internal/report"
|
||||
)
|
||||
|
||||
var (
|
||||
htmlTemplates *template.Template // Lazily loaded templates
|
||||
htmlTemplateInit sync.Once
|
||||
)
|
||||
|
||||
// getHTMLTemplates returns the set of HTML templates used by pprof,
|
||||
// initializing them if necessary.
|
||||
func getHTMLTemplates() *template.Template {
|
||||
htmlTemplateInit.Do(func() {
|
||||
htmlTemplates = template.New("templategroup")
|
||||
addTemplates(htmlTemplates)
|
||||
report.AddSourceTemplates(htmlTemplates)
|
||||
})
|
||||
return htmlTemplates
|
||||
}
|
||||
|
||||
//go:embed html
|
||||
var embeddedFiles embed.FS
|
||||
|
||||
|
@ -54,6 +73,7 @@ func addTemplates(templates *template.Template) {
|
|||
def("css", loadCSS("html/common.css"))
|
||||
def("header", loadFile("html/header.html"))
|
||||
def("graph", loadFile("html/graph.html"))
|
||||
def("graph_css", loadCSS("html/graph.css"))
|
||||
def("script", loadJS("html/common.js"))
|
||||
def("top", loadFile("html/top.html"))
|
||||
def("sourcelisting", loadFile("html/source.html"))
|
||||
|
|
32
src/cmd/vendor/github.com/google/pprof/internal/driver/webui.go
generated
vendored
32
src/cmd/vendor/github.com/google/pprof/internal/driver/webui.go
generated
vendored
|
@ -18,6 +18,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
gourl "net/url"
|
||||
|
@ -28,6 +29,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/google/pprof/internal/graph"
|
||||
"github.com/google/pprof/internal/measurement"
|
||||
"github.com/google/pprof/internal/plugin"
|
||||
"github.com/google/pprof/internal/report"
|
||||
"github.com/google/pprof/profile"
|
||||
|
@ -39,7 +41,6 @@ type webInterface struct {
|
|||
copier profileCopier
|
||||
options *plugin.Options
|
||||
help map[string]string
|
||||
templates *template.Template
|
||||
settingsFile string
|
||||
}
|
||||
|
||||
|
@ -48,15 +49,11 @@ func makeWebInterface(p *profile.Profile, copier profileCopier, opt *plugin.Opti
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
templates := template.New("templategroup")
|
||||
addTemplates(templates)
|
||||
report.AddSourceTemplates(templates)
|
||||
return &webInterface{
|
||||
prof: p,
|
||||
copier: copier,
|
||||
options: opt,
|
||||
help: make(map[string]string),
|
||||
templates: templates,
|
||||
settingsFile: settingsFile,
|
||||
}, nil
|
||||
}
|
||||
|
@ -82,14 +79,17 @@ type webArgs struct {
|
|||
Total int64
|
||||
SampleTypes []string
|
||||
Legend []string
|
||||
Standalone bool // True for command-line generation of HTML
|
||||
Help map[string]string
|
||||
Nodes []string
|
||||
HTMLBody template.HTML
|
||||
TextBody string
|
||||
Top []report.TextItem
|
||||
Listing report.WebListData
|
||||
FlameGraph template.JS
|
||||
Stacks template.JS
|
||||
Configs []configMenuEntry
|
||||
UnitDefs []measurement.UnitType
|
||||
}
|
||||
|
||||
func serveWebInterface(hostport string, p *profile.Profile, o *plugin.Options, disableBrowser bool) error {
|
||||
|
@ -283,21 +283,25 @@ func (ui *webInterface) makeReport(w http.ResponseWriter, req *http.Request,
|
|||
return rpt, catcher.errors
|
||||
}
|
||||
|
||||
// render generates html using the named template based on the contents of data.
|
||||
func (ui *webInterface) render(w http.ResponseWriter, req *http.Request, tmpl string,
|
||||
rpt *report.Report, errList, legend []string, data webArgs) {
|
||||
// renderHTML generates html using the named template based on the contents of data.
|
||||
func renderHTML(dst io.Writer, tmpl string, rpt *report.Report, errList, legend []string, data webArgs) error {
|
||||
file := getFromLegend(legend, "File: ", "unknown")
|
||||
profile := getFromLegend(legend, "Type: ", "unknown")
|
||||
data.Title = file + " " + profile
|
||||
data.Errors = errList
|
||||
data.Total = rpt.Total()
|
||||
data.SampleTypes = sampleTypes(ui.prof)
|
||||
data.Legend = legend
|
||||
return getHTMLTemplates().ExecuteTemplate(dst, tmpl, data)
|
||||
}
|
||||
|
||||
// render responds with html generated by passing data to the named template.
|
||||
func (ui *webInterface) render(w http.ResponseWriter, req *http.Request, tmpl string,
|
||||
rpt *report.Report, errList, legend []string, data webArgs) {
|
||||
data.SampleTypes = sampleTypes(ui.prof)
|
||||
data.Help = ui.help
|
||||
data.Configs = configMenu(ui.settingsFile, *req.URL)
|
||||
|
||||
html := &bytes.Buffer{}
|
||||
if err := ui.templates.ExecuteTemplate(html, tmpl, data); err != nil {
|
||||
if err := renderHTML(html, tmpl, rpt, errList, legend, data); err != nil {
|
||||
http.Error(w, "internal template error", http.StatusInternalServerError)
|
||||
ui.options.UI.PrintErr(err)
|
||||
return
|
||||
|
@ -410,8 +414,8 @@ func (ui *webInterface) source(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
// Generate source listing.
|
||||
var body bytes.Buffer
|
||||
if err := report.PrintWebList(&body, rpt, ui.options.Obj, maxEntries); err != nil {
|
||||
listing, err := report.MakeWebList(rpt, ui.options.Obj, maxEntries)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
ui.options.UI.PrintErr(err)
|
||||
return
|
||||
|
@ -419,7 +423,7 @@ func (ui *webInterface) source(w http.ResponseWriter, req *http.Request) {
|
|||
|
||||
legend := report.ProfileLabels(rpt)
|
||||
ui.render(w, req, "sourcelisting", rpt, errList, legend, webArgs{
|
||||
HTMLBody: template.HTML(body.String()),
|
||||
Listing: listing,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
7
src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go
generated
vendored
7
src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go
generated
vendored
|
@ -118,12 +118,7 @@ func parseNotes(reader io.Reader, alignment int, order binary.ByteOrder) ([]elfN
|
|||
//
|
||||
// If no build-ID was found but the binary was read without error, it returns
|
||||
// (nil, nil).
|
||||
func GetBuildID(binary io.ReaderAt) ([]byte, error) {
|
||||
f, err := elf.NewFile(binary)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func GetBuildID(f *elf.File) ([]byte, error) {
|
||||
findBuildID := func(notes []elfNote) ([]byte, error) {
|
||||
var buildID []byte
|
||||
for _, note := range notes {
|
||||
|
|
2
src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go
generated
vendored
2
src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go
generated
vendored
|
@ -444,7 +444,7 @@ func newTree(prof *profile.Profile, o *Options) (g *Graph) {
|
|||
}
|
||||
}
|
||||
|
||||
nodes := make(Nodes, len(prof.Location))
|
||||
nodes := make(Nodes, 0, len(prof.Location))
|
||||
for _, nm := range parentNodeMap {
|
||||
nodes = append(nodes, nm.nodes()...)
|
||||
}
|
||||
|
|
61
src/cmd/vendor/github.com/google/pprof/internal/measurement/measurement.go
generated
vendored
61
src/cmd/vendor/github.com/google/pprof/internal/measurement/measurement.go
generated
vendored
|
@ -113,7 +113,7 @@ func compatibleValueTypes(v1, v2 *profile.ValueType) bool {
|
|||
if v1.Unit == v2.Unit {
|
||||
return true
|
||||
}
|
||||
for _, ut := range unitTypes {
|
||||
for _, ut := range UnitTypes {
|
||||
if ut.sniffUnit(v1.Unit) != nil && ut.sniffUnit(v2.Unit) != nil {
|
||||
return true
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ func Scale(value int64, fromUnit, toUnit string) (float64, string) {
|
|||
v, u := Scale(-value, fromUnit, toUnit)
|
||||
return -v, u
|
||||
}
|
||||
for _, ut := range unitTypes {
|
||||
for _, ut := range UnitTypes {
|
||||
if v, u, ok := ut.convertUnit(value, fromUnit, toUnit); ok {
|
||||
return v, u
|
||||
}
|
||||
|
@ -177,26 +177,26 @@ func Percentage(value, total int64) string {
|
|||
}
|
||||
}
|
||||
|
||||
// unit includes a list of aliases representing a specific unit and a factor
|
||||
// Unit includes a list of aliases representing a specific unit and a factor
|
||||
// which one can multiple a value in the specified unit by to get the value
|
||||
// in terms of the base unit.
|
||||
type unit struct {
|
||||
canonicalName string
|
||||
type Unit struct {
|
||||
CanonicalName string
|
||||
aliases []string
|
||||
factor float64
|
||||
Factor float64
|
||||
}
|
||||
|
||||
// unitType includes a list of units that are within the same category (i.e.
|
||||
// UnitType includes a list of units that are within the same category (i.e.
|
||||
// memory or time units) and a default unit to use for this type of unit.
|
||||
type unitType struct {
|
||||
defaultUnit unit
|
||||
units []unit
|
||||
type UnitType struct {
|
||||
DefaultUnit Unit
|
||||
Units []Unit
|
||||
}
|
||||
|
||||
// findByAlias returns the unit associated with the specified alias. It returns
|
||||
// nil if the unit with such alias is not found.
|
||||
func (ut unitType) findByAlias(alias string) *unit {
|
||||
for _, u := range ut.units {
|
||||
func (ut UnitType) findByAlias(alias string) *Unit {
|
||||
for _, u := range ut.Units {
|
||||
for _, a := range u.aliases {
|
||||
if alias == a {
|
||||
return &u
|
||||
|
@ -208,7 +208,7 @@ func (ut unitType) findByAlias(alias string) *unit {
|
|||
|
||||
// sniffUnit simpifies the input alias and returns the unit associated with the
|
||||
// specified alias. It returns nil if the unit with such alias is not found.
|
||||
func (ut unitType) sniffUnit(unit string) *unit {
|
||||
func (ut UnitType) sniffUnit(unit string) *Unit {
|
||||
unit = strings.ToLower(unit)
|
||||
if len(unit) > 2 {
|
||||
unit = strings.TrimSuffix(unit, "s")
|
||||
|
@ -219,13 +219,13 @@ func (ut unitType) sniffUnit(unit string) *unit {
|
|||
// autoScale takes in the value with units of the base unit and returns
|
||||
// that value scaled to a reasonable unit if a reasonable unit is
|
||||
// found.
|
||||
func (ut unitType) autoScale(value float64) (float64, string, bool) {
|
||||
func (ut UnitType) autoScale(value float64) (float64, string, bool) {
|
||||
var f float64
|
||||
var unit string
|
||||
for _, u := range ut.units {
|
||||
if u.factor >= f && (value/u.factor) >= 1.0 {
|
||||
f = u.factor
|
||||
unit = u.canonicalName
|
||||
for _, u := range ut.Units {
|
||||
if u.Factor >= f && (value/u.Factor) >= 1.0 {
|
||||
f = u.Factor
|
||||
unit = u.CanonicalName
|
||||
}
|
||||
}
|
||||
if f == 0 {
|
||||
|
@ -239,27 +239,28 @@ func (ut unitType) autoScale(value float64) (float64, string, bool) {
|
|||
// included in the unitType, then a false boolean will be returned. If the
|
||||
// toUnit is not in the unitType, the value will be returned in terms of the
|
||||
// default unitType.
|
||||
func (ut unitType) convertUnit(value int64, fromUnitStr, toUnitStr string) (float64, string, bool) {
|
||||
func (ut UnitType) convertUnit(value int64, fromUnitStr, toUnitStr string) (float64, string, bool) {
|
||||
fromUnit := ut.sniffUnit(fromUnitStr)
|
||||
if fromUnit == nil {
|
||||
return 0, "", false
|
||||
}
|
||||
v := float64(value) * fromUnit.factor
|
||||
v := float64(value) * fromUnit.Factor
|
||||
if toUnitStr == "minimum" || toUnitStr == "auto" {
|
||||
if v, u, ok := ut.autoScale(v); ok {
|
||||
return v, u, true
|
||||
}
|
||||
return v / ut.defaultUnit.factor, ut.defaultUnit.canonicalName, true
|
||||
return v / ut.DefaultUnit.Factor, ut.DefaultUnit.CanonicalName, true
|
||||
}
|
||||
toUnit := ut.sniffUnit(toUnitStr)
|
||||
if toUnit == nil {
|
||||
return v / ut.defaultUnit.factor, ut.defaultUnit.canonicalName, true
|
||||
return v / ut.DefaultUnit.Factor, ut.DefaultUnit.CanonicalName, true
|
||||
}
|
||||
return v / toUnit.factor, toUnit.canonicalName, true
|
||||
return v / toUnit.Factor, toUnit.CanonicalName, true
|
||||
}
|
||||
|
||||
var unitTypes = []unitType{{
|
||||
units: []unit{
|
||||
// UnitTypes holds the definition of units known to pprof.
|
||||
var UnitTypes = []UnitType{{
|
||||
Units: []Unit{
|
||||
{"B", []string{"b", "byte"}, 1},
|
||||
{"kB", []string{"kb", "kbyte", "kilobyte"}, float64(1 << 10)},
|
||||
{"MB", []string{"mb", "mbyte", "megabyte"}, float64(1 << 20)},
|
||||
|
@ -267,18 +268,18 @@ var unitTypes = []unitType{{
|
|||
{"TB", []string{"tb", "tbyte", "terabyte"}, float64(1 << 40)},
|
||||
{"PB", []string{"pb", "pbyte", "petabyte"}, float64(1 << 50)},
|
||||
},
|
||||
defaultUnit: unit{"B", []string{"b", "byte"}, 1},
|
||||
DefaultUnit: Unit{"B", []string{"b", "byte"}, 1},
|
||||
}, {
|
||||
units: []unit{
|
||||
Units: []Unit{
|
||||
{"ns", []string{"ns", "nanosecond"}, float64(time.Nanosecond)},
|
||||
{"us", []string{"μs", "us", "microsecond"}, float64(time.Microsecond)},
|
||||
{"ms", []string{"ms", "millisecond"}, float64(time.Millisecond)},
|
||||
{"s", []string{"s", "sec", "second"}, float64(time.Second)},
|
||||
{"hrs", []string{"hour", "hr"}, float64(time.Hour)},
|
||||
},
|
||||
defaultUnit: unit{"s", []string{}, float64(time.Second)},
|
||||
DefaultUnit: Unit{"s", []string{}, float64(time.Second)},
|
||||
}, {
|
||||
units: []unit{
|
||||
Units: []Unit{
|
||||
{"n*GCU", []string{"nanogcu"}, 1e-9},
|
||||
{"u*GCU", []string{"microgcu"}, 1e-6},
|
||||
{"m*GCU", []string{"milligcu"}, 1e-3},
|
||||
|
@ -289,5 +290,5 @@ var unitTypes = []unitType{{
|
|||
{"T*GCU", []string{"teragcu"}, 1e12},
|
||||
{"P*GCU", []string{"petagcu"}, 1e15},
|
||||
},
|
||||
defaultUnit: unit{"GCU", []string{}, 1.0},
|
||||
DefaultUnit: Unit{"GCU", []string{}, 1.0},
|
||||
}}
|
||||
|
|
2
src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go
generated
vendored
2
src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go
generated
vendored
|
@ -175,7 +175,7 @@ type Sym struct {
|
|||
|
||||
// A UI manages user interactions.
|
||||
type UI interface {
|
||||
// Read returns a line of text (a command) read from the user.
|
||||
// ReadLine returns a line of text (a command) read from the user.
|
||||
// prompt is printed before reading the command.
|
||||
ReadLine(prompt string) (string, error)
|
||||
|
||||
|
|
8
src/cmd/vendor/github.com/google/pprof/internal/report/report.go
generated
vendored
8
src/cmd/vendor/github.com/google/pprof/internal/report/report.go
generated
vendored
|
@ -111,12 +111,11 @@ func Generate(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
|
|||
return printAssembly(w, rpt, obj)
|
||||
case List:
|
||||
return printSource(w, rpt)
|
||||
case WebList:
|
||||
return printWebSource(w, rpt, obj)
|
||||
case Callgrind:
|
||||
return printCallgrind(w, rpt)
|
||||
}
|
||||
return fmt.Errorf("unexpected output format")
|
||||
// Note: WebList handling is in driver package.
|
||||
return fmt.Errorf("unexpected output format %v", o.OutputFormat)
|
||||
}
|
||||
|
||||
// newTrimmedGraph creates a graph for this report, trimmed according
|
||||
|
@ -1327,6 +1326,9 @@ type Report struct {
|
|||
// Total returns the total number of samples in a report.
|
||||
func (rpt *Report) Total() int64 { return rpt.total }
|
||||
|
||||
// OutputFormat returns the output format for the report.
|
||||
func (rpt *Report) OutputFormat() int { return rpt.options.OutputFormat }
|
||||
|
||||
func abs64(i int64) int64 {
|
||||
if i < 0 {
|
||||
return -i
|
||||
|
|
223
src/cmd/vendor/github.com/google/pprof/internal/report/source.go
generated
vendored
223
src/cmd/vendor/github.com/google/pprof/internal/report/source.go
generated
vendored
|
@ -122,17 +122,6 @@ func printSource(w io.Writer, rpt *Report) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// printWebSource prints an annotated source listing, include all
|
||||
// functions with samples that match the regexp rpt.options.symbol.
|
||||
func printWebSource(w io.Writer, rpt *Report, obj plugin.ObjTool) error {
|
||||
printHeader(w, rpt)
|
||||
if err := PrintWebList(w, rpt, obj, -1); err != nil {
|
||||
return err
|
||||
}
|
||||
printPageClosing(w)
|
||||
return nil
|
||||
}
|
||||
|
||||
// sourcePrinter holds state needed for generating source+asm HTML listing.
|
||||
type sourcePrinter struct {
|
||||
reader *sourceReader
|
||||
|
@ -198,24 +187,73 @@ type addressRange struct {
|
|||
score int64 // Used to order ranges for processing
|
||||
}
|
||||
|
||||
// PrintWebList prints annotated source listing of rpt to w.
|
||||
// WebListData holds the data needed to generate HTML source code listing.
|
||||
type WebListData struct {
|
||||
Total string
|
||||
Files []WebListFile
|
||||
}
|
||||
|
||||
// WebListFile holds the per-file information for HTML source code listing.
|
||||
type WebListFile struct {
|
||||
Funcs []WebListFunc
|
||||
}
|
||||
|
||||
// WebListFunc holds the per-function information for HTML source code listing.
|
||||
type WebListFunc struct {
|
||||
Name string
|
||||
File string
|
||||
Flat string
|
||||
Cumulative string
|
||||
Percent string
|
||||
Lines []WebListLine
|
||||
}
|
||||
|
||||
// WebListLine holds the per-source-line information for HTML source code listing.
|
||||
type WebListLine struct {
|
||||
SrcLine string
|
||||
HTMLClass string
|
||||
Line int
|
||||
Flat string
|
||||
Cumulative string
|
||||
Instructions []WebListInstruction
|
||||
}
|
||||
|
||||
// WebListInstruction holds the per-instruction information for HTML source code listing.
|
||||
type WebListInstruction struct {
|
||||
NewBlock bool // Insert marker that indicates separation from previous block
|
||||
Flat string
|
||||
Cumulative string
|
||||
Synthetic bool
|
||||
Address uint64
|
||||
Disasm string
|
||||
FileLine string
|
||||
InlinedCalls []WebListCall
|
||||
}
|
||||
|
||||
// WebListCall holds the per-inlined-call information for HTML source code listing.
|
||||
type WebListCall struct {
|
||||
SrcLine string
|
||||
FileBase string
|
||||
Line int
|
||||
}
|
||||
|
||||
// MakeWebList returns an annotated source listing of rpt.
|
||||
// rpt.prof should contain inlined call info.
|
||||
func PrintWebList(w io.Writer, rpt *Report, obj plugin.ObjTool, maxFiles int) error {
|
||||
func MakeWebList(rpt *Report, obj plugin.ObjTool, maxFiles int) (WebListData, error) {
|
||||
sourcePath := rpt.options.SourcePath
|
||||
if sourcePath == "" {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not stat current dir: %v", err)
|
||||
return WebListData{}, fmt.Errorf("could not stat current dir: %v", err)
|
||||
}
|
||||
sourcePath = wd
|
||||
}
|
||||
sp := newSourcePrinter(rpt, obj, sourcePath)
|
||||
if len(sp.interest) == 0 {
|
||||
return fmt.Errorf("no matches found for regexp: %s", rpt.options.Symbol)
|
||||
return WebListData{}, fmt.Errorf("no matches found for regexp: %s", rpt.options.Symbol)
|
||||
}
|
||||
sp.print(w, maxFiles, rpt)
|
||||
sp.close()
|
||||
return nil
|
||||
defer sp.close()
|
||||
return sp.generate(maxFiles, rpt), nil
|
||||
}
|
||||
|
||||
func newSourcePrinter(rpt *Report, obj plugin.ObjTool, sourcePath string) *sourcePrinter {
|
||||
|
@ -566,7 +604,7 @@ func (sp *sourcePrinter) initSamples(flat, cum map[uint64]int64) {
|
|||
}
|
||||
}
|
||||
|
||||
func (sp *sourcePrinter) print(w io.Writer, maxFiles int, rpt *Report) {
|
||||
func (sp *sourcePrinter) generate(maxFiles int, rpt *Report) WebListData {
|
||||
// Finalize per-file counts.
|
||||
for _, file := range sp.files {
|
||||
seen := map[uint64]bool{}
|
||||
|
@ -598,19 +636,31 @@ func (sp *sourcePrinter) print(w io.Writer, maxFiles int, rpt *Report) {
|
|||
maxFiles = len(files)
|
||||
}
|
||||
sort.Slice(files, order)
|
||||
result := WebListData{
|
||||
Total: rpt.formatValue(rpt.total),
|
||||
}
|
||||
for i, f := range files {
|
||||
if i < maxFiles {
|
||||
sp.printFile(w, f, rpt)
|
||||
result.Files = append(result.Files, sp.generateFile(f, rpt))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (sp *sourcePrinter) printFile(w io.Writer, f *sourceFile, rpt *Report) {
|
||||
func (sp *sourcePrinter) generateFile(f *sourceFile, rpt *Report) WebListFile {
|
||||
var result WebListFile
|
||||
for _, fn := range sp.functions(f) {
|
||||
if fn.cum == 0 {
|
||||
continue
|
||||
}
|
||||
printFunctionHeader(w, fn.name, f.fname, fn.flat, fn.cum, rpt)
|
||||
|
||||
listfn := WebListFunc{
|
||||
Name: fn.name,
|
||||
File: f.fname,
|
||||
Flat: rpt.formatValue(fn.flat),
|
||||
Cumulative: rpt.formatValue(fn.cum),
|
||||
Percent: measurement.Percentage(fn.cum, rpt.total),
|
||||
}
|
||||
var asm []assemblyInstruction
|
||||
for l := fn.begin; l < fn.end; l++ {
|
||||
lineContents, ok := sp.reader.line(f.fname, l)
|
||||
|
@ -654,10 +704,12 @@ func (sp *sourcePrinter) printFile(w io.Writer, f *sourceFile, rpt *Report) {
|
|||
})
|
||||
}
|
||||
|
||||
printFunctionSourceLine(w, l, flatSum, cumSum, lineContents, asm, sp.reader, rpt)
|
||||
listfn.Lines = append(listfn.Lines, makeWebListLine(l, flatSum, cumSum, lineContents, asm, sp.reader, rpt))
|
||||
}
|
||||
printFunctionClosing(w)
|
||||
|
||||
result.Funcs = append(result.Funcs, listfn)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// functions splits apart the lines to show in a file into a list of per-function ranges.
|
||||
|
@ -752,89 +804,58 @@ func (sp *sourcePrinter) objectFile(m *profile.Mapping) plugin.ObjFile {
|
|||
return object
|
||||
}
|
||||
|
||||
// printHeader prints the page header for a weblist report.
|
||||
func printHeader(w io.Writer, rpt *Report) {
|
||||
fmt.Fprintln(w, `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Pprof listing</title>`)
|
||||
fmt.Fprintln(w, weblistPageCSS)
|
||||
fmt.Fprintln(w, weblistPageScript)
|
||||
fmt.Fprint(w, "</head>\n<body>\n\n")
|
||||
|
||||
var labels []string
|
||||
for _, l := range ProfileLabels(rpt) {
|
||||
labels = append(labels, template.HTMLEscapeString(l))
|
||||
// makeWebListLine returns the contents of a single line in a web listing. This includes
|
||||
// the source line and the corresponding assembly.
|
||||
func makeWebListLine(lineNo int, flat, cum int64, lineContents string,
|
||||
assembly []assemblyInstruction, reader *sourceReader, rpt *Report) WebListLine {
|
||||
line := WebListLine{
|
||||
SrcLine: lineContents,
|
||||
Line: lineNo,
|
||||
Flat: valueOrDot(flat, rpt),
|
||||
Cumulative: valueOrDot(cum, rpt),
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, `<div class="legend">%s<br>Total: %s</div>`,
|
||||
strings.Join(labels, "<br>\n"),
|
||||
rpt.formatValue(rpt.total),
|
||||
)
|
||||
}
|
||||
|
||||
// printFunctionHeader prints a function header for a weblist report.
|
||||
func printFunctionHeader(w io.Writer, name, path string, flatSum, cumSum int64, rpt *Report) {
|
||||
fmt.Fprintf(w, `<h2>%s</h2><p class="filename">%s</p>
|
||||
<pre onClick="pprof_toggle_asm(event)">
|
||||
Total: %10s %10s (flat, cum) %s
|
||||
`,
|
||||
template.HTMLEscapeString(name), template.HTMLEscapeString(path),
|
||||
rpt.formatValue(flatSum), rpt.formatValue(cumSum),
|
||||
measurement.Percentage(cumSum, rpt.total))
|
||||
}
|
||||
|
||||
// printFunctionSourceLine prints a source line and the corresponding assembly.
|
||||
func printFunctionSourceLine(w io.Writer, lineNo int, flat, cum int64, lineContents string,
|
||||
assembly []assemblyInstruction, reader *sourceReader, rpt *Report) {
|
||||
if len(assembly) == 0 {
|
||||
fmt.Fprintf(w,
|
||||
"<span class=line> %6d</span> <span class=nop> %10s %10s %8s %s </span>\n",
|
||||
lineNo,
|
||||
valueOrDot(flat, rpt), valueOrDot(cum, rpt),
|
||||
"", template.HTMLEscapeString(lineContents))
|
||||
return
|
||||
line.HTMLClass = "nop"
|
||||
return line
|
||||
}
|
||||
|
||||
nestedInfo := false
|
||||
cl := "deadsrc"
|
||||
line.HTMLClass = "deadsrc"
|
||||
for _, an := range assembly {
|
||||
if len(an.inlineCalls) > 0 || an.instruction != synthAsm {
|
||||
nestedInfo = true
|
||||
cl = "livesrc"
|
||||
line.HTMLClass = "livesrc"
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(w,
|
||||
"<span class=line> %6d</span> <span class=%s> %10s %10s %8s %s </span>",
|
||||
lineNo, cl,
|
||||
valueOrDot(flat, rpt), valueOrDot(cum, rpt),
|
||||
"", template.HTMLEscapeString(lineContents))
|
||||
if nestedInfo {
|
||||
srcIndent := indentation(lineContents)
|
||||
printNested(w, srcIndent, assembly, reader, rpt)
|
||||
line.Instructions = makeWebListInstructions(srcIndent, assembly, reader, rpt)
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
return line
|
||||
}
|
||||
|
||||
func printNested(w io.Writer, srcIndent int, assembly []assemblyInstruction, reader *sourceReader, rpt *Report) {
|
||||
fmt.Fprint(w, "<span class=asm>")
|
||||
func makeWebListInstructions(srcIndent int, assembly []assemblyInstruction, reader *sourceReader, rpt *Report) []WebListInstruction {
|
||||
var result []WebListInstruction
|
||||
var curCalls []callID
|
||||
for i, an := range assembly {
|
||||
if an.startsBlock && i != 0 {
|
||||
// Insert a separator between discontiguous blocks.
|
||||
fmt.Fprintf(w, " %8s %28s\n", "", "⋮")
|
||||
}
|
||||
|
||||
var fileline string
|
||||
if an.file != "" {
|
||||
fileline = fmt.Sprintf("%s:%d", template.HTMLEscapeString(filepath.Base(an.file)), an.line)
|
||||
}
|
||||
flat, cum := an.flat, an.cum
|
||||
text := strings.Repeat(" ", srcIndent+4+4*len(an.inlineCalls)) + an.instruction
|
||||
inst := WebListInstruction{
|
||||
NewBlock: (an.startsBlock && i != 0),
|
||||
Flat: valueOrDot(an.flat, rpt),
|
||||
Cumulative: valueOrDot(an.cum, rpt),
|
||||
Synthetic: (an.instruction == synthAsm),
|
||||
Address: an.address,
|
||||
Disasm: rightPad(text, 80),
|
||||
FileLine: fileline,
|
||||
}
|
||||
|
||||
// Print inlined call context.
|
||||
// Add inlined call context.
|
||||
for j, c := range an.inlineCalls {
|
||||
if j < len(curCalls) && curCalls[j] == c {
|
||||
// Skip if same as previous instruction.
|
||||
|
@ -845,36 +866,18 @@ func printNested(w io.Writer, srcIndent int, assembly []assemblyInstruction, rea
|
|||
if !ok {
|
||||
fline = ""
|
||||
}
|
||||
text := strings.Repeat(" ", srcIndent+4+4*j) + strings.TrimSpace(fline)
|
||||
fmt.Fprintf(w, " %8s %10s %10s %8s <span class=inlinesrc>%s</span> <span class=unimportant>%s:%d</span>\n",
|
||||
"", "", "", "",
|
||||
template.HTMLEscapeString(rightPad(text, 80)),
|
||||
template.HTMLEscapeString(filepath.Base(c.file)), c.line)
|
||||
srcCode := strings.Repeat(" ", srcIndent+4+4*j) + strings.TrimSpace(fline)
|
||||
inst.InlinedCalls = append(inst.InlinedCalls, WebListCall{
|
||||
SrcLine: rightPad(srcCode, 80),
|
||||
FileBase: filepath.Base(c.file),
|
||||
Line: c.line,
|
||||
})
|
||||
}
|
||||
curCalls = an.inlineCalls
|
||||
if an.instruction == synthAsm {
|
||||
continue
|
||||
}
|
||||
text := strings.Repeat(" ", srcIndent+4+4*len(curCalls)) + an.instruction
|
||||
fmt.Fprintf(w, " %8s %10s %10s %8x: %s <span class=unimportant>%s</span>\n",
|
||||
"", valueOrDot(flat, rpt), valueOrDot(cum, rpt), an.address,
|
||||
template.HTMLEscapeString(rightPad(text, 80)),
|
||||
// fileline should not be escaped since it was formed by appending
|
||||
// line number (just digits) to an escaped file name. Escaping here
|
||||
// would cause double-escaping of file name.
|
||||
fileline)
|
||||
|
||||
result = append(result, inst)
|
||||
}
|
||||
fmt.Fprint(w, "</span>")
|
||||
}
|
||||
|
||||
// printFunctionClosing prints the end of a function in a weblist report.
|
||||
func printFunctionClosing(w io.Writer) {
|
||||
fmt.Fprintln(w, "</pre>")
|
||||
}
|
||||
|
||||
// printPageClosing prints the end of the page in a weblist report.
|
||||
func printPageClosing(w io.Writer) {
|
||||
fmt.Fprintln(w, weblistPageClosing)
|
||||
return result
|
||||
}
|
||||
|
||||
// getSourceFromFile collects the sources of a function from a source
|
||||
|
|
4
src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go
generated
vendored
4
src/cmd/vendor/github.com/google/pprof/internal/report/source_html.go
generated
vendored
|
@ -69,7 +69,3 @@ function pprof_toggle_asm(e) {
|
|||
}
|
||||
}
|
||||
</script>`
|
||||
|
||||
const weblistPageClosing = `
|
||||
</body>
|
||||
</html>`
|
||||
|
|
177
src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go
generated
vendored
177
src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go
generated
vendored
|
@ -133,22 +133,80 @@ func doLocalSymbolize(prof *profile.Profile, fast, force bool, obj plugin.ObjToo
|
|||
}
|
||||
}
|
||||
|
||||
mt, err := newMapping(prof, obj, ui, force)
|
||||
if err != nil {
|
||||
return err
|
||||
functions := map[profile.Function]*profile.Function{}
|
||||
addFunction := func(f *profile.Function) *profile.Function {
|
||||
if fp := functions[*f]; fp != nil {
|
||||
return fp
|
||||
}
|
||||
functions[*f] = f
|
||||
f.ID = uint64(len(prof.Function)) + 1
|
||||
prof.Function = append(prof.Function, f)
|
||||
return f
|
||||
}
|
||||
defer mt.close()
|
||||
|
||||
functions := make(map[profile.Function]*profile.Function)
|
||||
for _, l := range mt.prof.Location {
|
||||
m := l.Mapping
|
||||
segment := mt.segments[m]
|
||||
if segment == nil {
|
||||
// Nothing to do.
|
||||
missingBinaries := false
|
||||
mappingLocs := map[*profile.Mapping][]*profile.Location{}
|
||||
for _, l := range prof.Location {
|
||||
mappingLocs[l.Mapping] = append(mappingLocs[l.Mapping], l)
|
||||
}
|
||||
for midx, m := range prof.Mapping {
|
||||
locs := mappingLocs[m]
|
||||
if len(locs) == 0 {
|
||||
// The mapping is dangling and has no locations pointing to it.
|
||||
continue
|
||||
}
|
||||
// Do not attempt to re-symbolize a mapping that has already been symbolized.
|
||||
if !force && (m.HasFunctions || m.HasFilenames || m.HasLineNumbers) {
|
||||
continue
|
||||
}
|
||||
if m.File == "" {
|
||||
if midx == 0 {
|
||||
ui.PrintErr("Main binary filename not available.")
|
||||
continue
|
||||
}
|
||||
missingBinaries = true
|
||||
continue
|
||||
}
|
||||
if m.Unsymbolizable() {
|
||||
// Skip well-known system mappings
|
||||
continue
|
||||
}
|
||||
if m.BuildID == "" {
|
||||
if u, err := url.Parse(m.File); err == nil && u.IsAbs() && strings.Contains(strings.ToLower(u.Scheme), "http") {
|
||||
// Skip mappings pointing to a source URL
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
stack, err := segment.SourceLine(l.Address)
|
||||
name := filepath.Base(m.File)
|
||||
if m.BuildID != "" {
|
||||
name += fmt.Sprintf(" (build ID %s)", m.BuildID)
|
||||
}
|
||||
f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol)
|
||||
if err != nil {
|
||||
ui.PrintErr("Local symbolization failed for ", name, ": ", err)
|
||||
missingBinaries = true
|
||||
continue
|
||||
}
|
||||
if fid := f.BuildID(); m.BuildID != "" && fid != "" && fid != m.BuildID {
|
||||
ui.PrintErr("Local symbolization failed for ", name, ": build ID mismatch")
|
||||
f.Close()
|
||||
continue
|
||||
}
|
||||
symbolizeOneMapping(m, locs, f, addFunction)
|
||||
f.Close()
|
||||
}
|
||||
|
||||
if missingBinaries {
|
||||
ui.PrintErr("Some binary filenames not available. Symbolization may be incomplete.\n" +
|
||||
"Try setting PPROF_BINARY_PATH to the search path for local binaries.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func symbolizeOneMapping(m *profile.Mapping, locs []*profile.Location, obj plugin.ObjFile, addFunction func(*profile.Function) *profile.Function) {
|
||||
for _, l := range locs {
|
||||
stack, err := obj.SourceLine(l.Address)
|
||||
if err != nil || len(stack) == 0 {
|
||||
// No answers from addr2line.
|
||||
continue
|
||||
|
@ -166,18 +224,11 @@ func doLocalSymbolize(prof *profile.Profile, fast, force bool, obj plugin.ObjToo
|
|||
if frame.Line != 0 {
|
||||
m.HasLineNumbers = true
|
||||
}
|
||||
f := &profile.Function{
|
||||
f := addFunction(&profile.Function{
|
||||
Name: frame.Func,
|
||||
SystemName: frame.Func,
|
||||
Filename: frame.File,
|
||||
}
|
||||
if fp := functions[*f]; fp != nil {
|
||||
f = fp
|
||||
} else {
|
||||
functions[*f] = f
|
||||
f.ID = uint64(len(mt.prof.Function)) + 1
|
||||
mt.prof.Function = append(mt.prof.Function, f)
|
||||
}
|
||||
})
|
||||
l.Line[i] = profile.Line{
|
||||
Function: f,
|
||||
Line: int64(frame.Line),
|
||||
|
@ -189,8 +240,6 @@ func doLocalSymbolize(prof *profile.Profile, fast, force bool, obj plugin.ObjToo
|
|||
m.HasInlineFrames = true
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Demangle updates the function names in a profile with demangled C++
|
||||
|
@ -294,87 +343,3 @@ func removeMatching(name string, start, end byte) string {
|
|||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// newMapping creates a mappingTable for a profile.
|
||||
func newMapping(prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, force bool) (*mappingTable, error) {
|
||||
mt := &mappingTable{
|
||||
prof: prof,
|
||||
segments: make(map[*profile.Mapping]plugin.ObjFile),
|
||||
}
|
||||
|
||||
// Identify used mappings
|
||||
mappings := make(map[*profile.Mapping]bool)
|
||||
for _, l := range prof.Location {
|
||||
mappings[l.Mapping] = true
|
||||
}
|
||||
|
||||
missingBinaries := false
|
||||
for midx, m := range prof.Mapping {
|
||||
if !mappings[m] {
|
||||
continue
|
||||
}
|
||||
|
||||
// Do not attempt to re-symbolize a mapping that has already been symbolized.
|
||||
if !force && (m.HasFunctions || m.HasFilenames || m.HasLineNumbers) {
|
||||
continue
|
||||
}
|
||||
|
||||
if m.File == "" {
|
||||
if midx == 0 {
|
||||
ui.PrintErr("Main binary filename not available.")
|
||||
continue
|
||||
}
|
||||
missingBinaries = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip well-known system mappings
|
||||
if m.Unsymbolizable() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip mappings pointing to a source URL
|
||||
if m.BuildID == "" {
|
||||
if u, err := url.Parse(m.File); err == nil && u.IsAbs() && strings.Contains(strings.ToLower(u.Scheme), "http") {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
name := filepath.Base(m.File)
|
||||
if m.BuildID != "" {
|
||||
name += fmt.Sprintf(" (build ID %s)", m.BuildID)
|
||||
}
|
||||
f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol)
|
||||
if err != nil {
|
||||
ui.PrintErr("Local symbolization failed for ", name, ": ", err)
|
||||
missingBinaries = true
|
||||
continue
|
||||
}
|
||||
if fid := f.BuildID(); m.BuildID != "" && fid != "" && fid != m.BuildID {
|
||||
ui.PrintErr("Local symbolization failed for ", name, ": build ID mismatch")
|
||||
f.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
mt.segments[m] = f
|
||||
}
|
||||
if missingBinaries {
|
||||
ui.PrintErr("Some binary filenames not available. Symbolization may be incomplete.\n" +
|
||||
"Try setting PPROF_BINARY_PATH to the search path for local binaries.")
|
||||
}
|
||||
return mt, nil
|
||||
}
|
||||
|
||||
// mappingTable contains the mechanisms for symbolization of a
|
||||
// profile.
|
||||
type mappingTable struct {
|
||||
prof *profile.Profile
|
||||
segments map[*profile.Mapping]plugin.ObjFile
|
||||
}
|
||||
|
||||
// close releases any external processes being used for the mapping.
|
||||
func (mt *mappingTable) close() {
|
||||
for _, segment := range mt.segments {
|
||||
segment.Close()
|
||||
}
|
||||
}
|
||||
|
|
2
src/cmd/vendor/github.com/google/pprof/profile/profile.go
generated
vendored
2
src/cmd/vendor/github.com/google/pprof/profile/profile.go
generated
vendored
|
@ -847,7 +847,7 @@ func (p *Profile) HasFileLines() bool {
|
|||
// "[vdso]", [vsyscall]" and some others, see the code.
|
||||
func (m *Mapping) Unsymbolizable() bool {
|
||||
name := filepath.Base(m.File)
|
||||
return strings.HasPrefix(name, "[") || strings.HasPrefix(name, "linux-vdso") || strings.HasPrefix(m.File, "/dev/dri/")
|
||||
return strings.HasPrefix(name, "[") || strings.HasPrefix(name, "linux-vdso") || strings.HasPrefix(m.File, "/dev/dri/") || m.File == "//anon"
|
||||
}
|
||||
|
||||
// Copy makes a fully independent copy of a profile.
|
||||
|
|
1392
src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go
generated
vendored
1392
src/cmd/vendor/github.com/ianlancetaylor/demangle/ast.go
generated
vendored
File diff suppressed because it is too large
Load diff
669
src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go
generated
vendored
669
src/cmd/vendor/github.com/ianlancetaylor/demangle/demangle.go
generated
vendored
File diff suppressed because it is too large
Load diff
4
src/cmd/vendor/modules.txt
vendored
4
src/cmd/vendor/modules.txt
vendored
|
@ -1,4 +1,4 @@
|
|||
# github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5
|
||||
# github.com/google/pprof v0.0.0-20240528025155-186aa0362fba
|
||||
## explicit; go 1.19
|
||||
github.com/google/pprof/driver
|
||||
github.com/google/pprof/internal/binutils
|
||||
|
@ -13,7 +13,7 @@ github.com/google/pprof/internal/symbolz
|
|||
github.com/google/pprof/internal/transport
|
||||
github.com/google/pprof/profile
|
||||
github.com/google/pprof/third_party/svgpan
|
||||
# github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab
|
||||
# github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465
|
||||
## explicit; go 1.13
|
||||
github.com/ianlancetaylor/demangle
|
||||
# golang.org/x/arch v0.7.0
|
||||
|
|
Loading…
Reference in a new issue