mirror of https://github.com/golang/go.git
cmd: update vendored pprof
go get github.com/google/pprof@latest go mod vendor Plus a tiny change to the pprof command to match an upstream interface change. Updates #36905. Change-Id: I4c7bbe8c317a6eeb217fce971b208f96ab0727fa Reviewed-on: https://go-review.googlesource.com/c/go/+/393370 Trust: Heschi Kreinick <heschi@google.com> Run-TryBot: Heschi Kreinick <heschi@google.com> Auto-Submit: Heschi Kreinick <heschi@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
9f252a0462
commit
7e5804cb70
|
|
@ -3,7 +3,7 @@ module cmd
|
|||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31
|
||||
github.com/google/pprof v0.0.0-20220314021825-5bba342933ea
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31 h1:YvpxjnjGhf/vDEeYOysNbsrtB///PKS8lqkFNSDm1p8=
|
||||
github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||
github.com/google/pprof v0.0.0-20220314021825-5bba342933ea h1:yVDp4C9ff/qoEAhHNf5cqk/YTxTGECSzGYzahdhEKBI=
|
||||
github.com/google/pprof v0.0.0-20220314021825-5bba342933ea/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d h1:uGg2frlt3IcT7kbV6LEp5ONv4vmoO2FW4qSO+my/aoM=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ type objTool struct {
|
|||
disasmCache map[string]*objfile.Disasm
|
||||
}
|
||||
|
||||
func (*objTool) Open(name string, start, limit, offset uint64) (driver.ObjFile, error) {
|
||||
func (*objTool) Open(name string, start, limit, offset uint64, relocationSymbol string) (driver.ObjFile, error) {
|
||||
of, err := objfile.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -137,8 +137,10 @@ type MappingSources map[string][]struct {
|
|||
type ObjTool interface {
|
||||
// Open opens the named object file. If the object is a shared
|
||||
// library, start/limit/offset are the addresses where it is mapped
|
||||
// into memory in the address space being inspected.
|
||||
Open(file string, start, limit, offset uint64) (ObjFile, error)
|
||||
// into memory in the address space being inspected. If the object
|
||||
// is a linux kernel, relocationSymbol is the name of the symbol
|
||||
// corresponding to the start address.
|
||||
Open(file string, start, limit, offset uint64, relocationSymbol string) (ObjFile, error)
|
||||
|
||||
// Disasm disassembles the named object file, starting at
|
||||
// the start address and stopping at (before) the end address.
|
||||
|
|
@ -232,8 +234,8 @@ type internalObjTool struct {
|
|||
ObjTool
|
||||
}
|
||||
|
||||
func (o *internalObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) {
|
||||
f, err := o.ObjTool.Open(file, start, limit, offset)
|
||||
func (o *internalObjTool) Open(file string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) {
|
||||
f, err := o.ObjTool.Open(file, start, limit, offset, relocationSymbol)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ func (bu *Binutils) Disasm(file string, start, end uint64, intelSyntax bool) ([]
|
|||
}
|
||||
|
||||
// Open satisfies the plugin.ObjTool interface.
|
||||
func (bu *Binutils) Open(name string, start, limit, offset uint64) (plugin.ObjFile, error) {
|
||||
func (bu *Binutils) Open(name string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) {
|
||||
b := bu.get()
|
||||
|
||||
// Make sure file is a supported executable.
|
||||
|
|
@ -316,7 +316,7 @@ func (bu *Binutils) Open(name string, start, limit, offset uint64) (plugin.ObjFi
|
|||
|
||||
// Match against supported file types.
|
||||
if elfMagic == elf.ELFMAG {
|
||||
f, err := b.openELF(name, start, limit, offset)
|
||||
f, err := b.openELF(name, start, limit, offset, relocationSymbol)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading ELF file %s: %v", name, err)
|
||||
}
|
||||
|
|
@ -425,7 +425,7 @@ func (b *binrep) openMachO(name string, start, limit, offset uint64) (plugin.Obj
|
|||
return b.openMachOCommon(name, of, start, limit, offset)
|
||||
}
|
||||
|
||||
func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFile, error) {
|
||||
func (b *binrep) openELF(name string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) {
|
||||
ef, err := elfOpen(name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing %s: %v", name, err)
|
||||
|
|
@ -440,8 +440,8 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi
|
|||
}
|
||||
|
||||
var (
|
||||
stextOffset *uint64
|
||||
pageAligned = func(addr uint64) bool { return addr%4096 == 0 }
|
||||
kernelOffset *uint64
|
||||
pageAligned = func(addr uint64) bool { return addr%4096 == 0 }
|
||||
)
|
||||
if strings.Contains(name, "vmlinux") || !pageAligned(start) || !pageAligned(limit) || !pageAligned(offset) {
|
||||
// Reading all Symbols is expensive, and we only rarely need it so
|
||||
|
|
@ -455,10 +455,18 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi
|
|||
if err != nil && err != elf.ErrNoSymbols {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The kernel relocation symbol (the mapping start address) can be either
|
||||
// _text or _stext. When profiles are generated by `perf`, which one was used is
|
||||
// distinguished by the mapping name for the kernel image:
|
||||
// '[kernel.kallsyms]_text' or '[kernel.kallsyms]_stext', respectively. If we haven't
|
||||
// been able to parse it from the mapping, we default to _stext.
|
||||
if relocationSymbol == "" {
|
||||
relocationSymbol = "_stext"
|
||||
}
|
||||
for _, s := range symbols {
|
||||
if s.Name == "_stext" {
|
||||
// The kernel may use _stext as the mapping start address.
|
||||
stextOffset = &s.Value
|
||||
if s.Name == relocationSymbol {
|
||||
kernelOffset = &s.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -469,7 +477,7 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi
|
|||
// value until we have a sample address for this mapping, so that we can
|
||||
// correctly identify the associated program segment that is needed to compute
|
||||
// the base.
|
||||
if _, err := elfexec.GetBase(&ef.FileHeader, elfexec.FindTextProgHeader(ef), stextOffset, start, limit, offset); err != nil {
|
||||
if _, err := elfexec.GetBase(&ef.FileHeader, elfexec.FindTextProgHeader(ef), kernelOffset, start, limit, offset); err != nil {
|
||||
return nil, fmt.Errorf("could not identify base for %s: %v", name, err)
|
||||
}
|
||||
|
||||
|
|
@ -478,14 +486,14 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi
|
|||
b: b,
|
||||
name: name,
|
||||
buildID: buildID,
|
||||
m: &elfMapping{start: start, limit: limit, offset: offset, stextOffset: stextOffset},
|
||||
m: &elfMapping{start: start, limit: limit, offset: offset, kernelOffset: kernelOffset},
|
||||
}}, nil
|
||||
}
|
||||
return &fileAddr2Line{file: file{
|
||||
b: b,
|
||||
name: name,
|
||||
buildID: buildID,
|
||||
m: &elfMapping{start: start, limit: limit, offset: offset, stextOffset: stextOffset},
|
||||
m: &elfMapping{start: start, limit: limit, offset: offset, kernelOffset: kernelOffset},
|
||||
}}, nil
|
||||
}
|
||||
|
||||
|
|
@ -521,8 +529,8 @@ func (b *binrep) openPE(name string, start, limit, offset uint64) (plugin.ObjFil
|
|||
type elfMapping struct {
|
||||
// Runtime mapping parameters.
|
||||
start, limit, offset uint64
|
||||
// Offset of _stext symbol. Only defined for kernel images, nil otherwise.
|
||||
stextOffset *uint64
|
||||
// Offset of kernel relocation symbol. Only defined for kernel images, nil otherwise.
|
||||
kernelOffset *uint64
|
||||
}
|
||||
|
||||
// findProgramHeader returns the program segment that matches the current
|
||||
|
|
@ -535,7 +543,7 @@ func (m *elfMapping) findProgramHeader(ef *elf.File, addr uint64) (*elf.ProgHead
|
|||
// it's a kernel / .ko module mapping, because with quipper address remapping
|
||||
// enabled, the address would be in the lower half of the address space.
|
||||
|
||||
if m.stextOffset != nil || m.start >= m.limit || m.limit >= (uint64(1)<<63) {
|
||||
if m.kernelOffset != nil || m.start >= m.limit || m.limit >= (uint64(1)<<63) {
|
||||
// For the kernel, find the program segment that includes the .text section.
|
||||
return elfexec.FindTextProgHeader(ef), nil
|
||||
}
|
||||
|
|
@ -601,7 +609,7 @@ func (f *file) computeBase(addr uint64) error {
|
|||
return fmt.Errorf("failed to find program header for file %q, ELF mapping %#v, address %x: %v", f.name, *f.m, addr, err)
|
||||
}
|
||||
|
||||
base, err := elfexec.GetBase(&ef.FileHeader, ph, f.m.stextOffset, f.m.start, f.m.limit, f.m.offset)
|
||||
base, err := elfexec.GetBase(&ef.FileHeader, ph, f.m.kernelOffset, f.m.start, f.m.limit, f.m.offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func parseFlags(o *plugin.Options) (*source, []string, error) {
|
|||
// Recognize first argument as an executable or buildid override.
|
||||
if len(args) > 1 {
|
||||
arg0 := args[0]
|
||||
if file, err := o.Obj.Open(arg0, 0, ^uint64(0), 0); err == nil {
|
||||
if file, err := o.Obj.Open(arg0, 0, ^uint64(0), 0, ""); err == nil {
|
||||
file.Close()
|
||||
execName = arg0
|
||||
args = args[1:]
|
||||
|
|
|
|||
|
|
@ -420,12 +420,14 @@ mapping:
|
|||
fileNames = append(fileNames, filepath.Join(path, m.File))
|
||||
}
|
||||
for _, name := range fileNames {
|
||||
if f, err := obj.Open(name, m.Start, m.Limit, m.Offset); err == nil {
|
||||
if f, err := obj.Open(name, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol); err == nil {
|
||||
defer f.Close()
|
||||
fileBuildID := f.BuildID()
|
||||
if m.BuildID != "" && m.BuildID != fileBuildID {
|
||||
ui.PrintErr("Ignoring local file " + name + ": build-id mismatch (" + m.BuildID + " != " + fileBuildID + ")")
|
||||
} else {
|
||||
// Explicitly do not update KernelRelocationSymbol --
|
||||
// the new local file name is most likely missing it.
|
||||
m.File = name
|
||||
continue mapping
|
||||
}
|
||||
|
|
@ -449,6 +451,8 @@ mapping:
|
|||
if execName, buildID := s.ExecName, s.BuildID; execName != "" || buildID != "" {
|
||||
m := p.Mapping[0]
|
||||
if execName != "" {
|
||||
// Explicitly do not update KernelRelocationSymbol --
|
||||
// the source override is most likely missing it.
|
||||
m.File = execName
|
||||
}
|
||||
if buildID != "" {
|
||||
|
|
|
|||
|
|
@ -17,13 +17,11 @@ package driver
|
|||
import (
|
||||
"html/template"
|
||||
|
||||
"github.com/google/pprof/third_party/d3"
|
||||
"github.com/google/pprof/third_party/d3flamegraph"
|
||||
)
|
||||
|
||||
// addTemplates adds a set of template definitions to templates.
|
||||
func addTemplates(templates *template.Template) {
|
||||
template.Must(templates.Parse(`{{define "d3script"}}` + d3.JSSource + `{{end}}`))
|
||||
template.Must(templates.Parse(`{{define "d3flamegraphscript"}}` + d3flamegraph.JSSource + `{{end}}`))
|
||||
template.Must(templates.Parse(`{{define "d3flamegraphcss"}}` + d3flamegraph.CSSSource + `{{end}}`))
|
||||
template.Must(templates.Parse(`
|
||||
|
|
@ -1329,40 +1327,29 @@ function viewer(baseUrl, nodes) {
|
|||
</div>
|
||||
{{template "script" .}}
|
||||
<script>viewer(new URL(window.location.href), {{.Nodes}});</script>
|
||||
<script>{{template "d3script" .}}</script>
|
||||
<script>{{template "d3flamegraphscript" .}}</script>
|
||||
<script>
|
||||
var data = {{.FlameGraph}};
|
||||
|
||||
var width = document.getElementById('chart').clientWidth;
|
||||
|
||||
var flameGraph = d3.flamegraph()
|
||||
var flameGraph = flamegraph()
|
||||
.width(width)
|
||||
.cellHeight(18)
|
||||
.minFrameSize(1)
|
||||
.transitionDuration(750)
|
||||
.transitionEase(d3.easeCubic)
|
||||
.inverted(true)
|
||||
.sort(true)
|
||||
.title('')
|
||||
.tooltip(false)
|
||||
.details(document.getElementById('flamegraphdetails'));
|
||||
.setDetailsElement(document.getElementById('flamegraphdetails'));
|
||||
|
||||
// <full name> (percentage, value)
|
||||
flameGraph.label((d) => d.data.f + ' (' + d.data.p + ', ' + d.data.l + ')');
|
||||
|
||||
(function(flameGraph) {
|
||||
var oldColorMapper = flameGraph.color();
|
||||
function colorMapper(d) {
|
||||
// Hack to force default color mapper to use 'warm' color scheme by not passing libtype
|
||||
const { data, highlight } = d;
|
||||
return oldColorMapper({ data: { n: data.n }, highlight });
|
||||
}
|
||||
flameGraph.setColorHue('warm');
|
||||
|
||||
flameGraph.color(colorMapper);
|
||||
}(flameGraph));
|
||||
|
||||
d3.select('#chart')
|
||||
select('#chart')
|
||||
.datum(data)
|
||||
.call(flameGraph);
|
||||
|
||||
|
|
|
|||
|
|
@ -165,9 +165,9 @@ func GetBuildID(binary io.ReaderAt) ([]byte, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// kernelBase caluclates the base for kernel mappings, which usually require
|
||||
// kernelBase calculates the base for kernel mappings, which usually require
|
||||
// special handling. For kernel mappings, tools (like perf) use the address of
|
||||
// the kernel relocation symbol (_text or _stext) as the mmap start. Additionaly,
|
||||
// the kernel relocation symbol (_text or _stext) as the mmap start. Additionally,
|
||||
// for obfuscation, ChromeOS profiles have the kernel image remapped to the 0-th page.
|
||||
func kernelBase(loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, bool) {
|
||||
const (
|
||||
|
|
@ -217,7 +217,7 @@ func kernelBase(loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit,
|
|||
// GetBase determines the base address to subtract from virtual
|
||||
// address to get symbol table address. For an executable, the base
|
||||
// is 0. Otherwise, it's a shared library, and the base is the
|
||||
// address where the mapping starts. The kernel needs special hanldling.
|
||||
// address where the mapping starts. The kernel needs special handling.
|
||||
func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, error) {
|
||||
|
||||
if start == 0 && offset == 0 && (limit == ^uint64(0) || limit == 0) {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ func (b *builder) addLegend() {
|
|||
return
|
||||
}
|
||||
title := labels[0]
|
||||
fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, title)
|
||||
fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, escapeForDot(title))
|
||||
fmt.Fprintf(b, ` label="%s\l"`, strings.Join(escapeAllForDot(labels), `\l`))
|
||||
if b.config.LegendURL != "" {
|
||||
fmt.Fprintf(b, ` URL="%s" target="_blank"`, b.config.LegendURL)
|
||||
|
|
@ -485,7 +485,7 @@ func escapeAllForDot(in []string) []string {
|
|||
|
||||
// escapeForDot escapes double quotes and backslashes, and replaces Graphviz's
|
||||
// "center" character (\n) with a left-justified character.
|
||||
// See https://graphviz.org/doc/info/attrs.html#k:escString for more info.
|
||||
// See https://graphviz.org/docs/attr-types/escString/ for more info.
|
||||
func escapeForDot(str string) string {
|
||||
return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(str, `\`, `\\`), `"`, `\"`), "\n", `\l`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,8 +109,10 @@ type MappingSources map[string][]struct {
|
|||
type ObjTool interface {
|
||||
// Open opens the named object file. If the object is a shared
|
||||
// library, start/limit/offset are the addresses where it is mapped
|
||||
// into memory in the address space being inspected.
|
||||
Open(file string, start, limit, offset uint64) (ObjFile, error)
|
||||
// into memory in the address space being inspected. If the object
|
||||
// is a linux kernel, relocationSymbol is the name of the symbol
|
||||
// corresponding to the start address.
|
||||
Open(file string, start, limit, offset uint64, relocationSymbol string) (ObjFile, error)
|
||||
|
||||
// Disasm disassembles the named object file, starting at
|
||||
// the start address and stopping at (before) the end address.
|
||||
|
|
|
|||
|
|
@ -526,7 +526,7 @@ func symbolsFromBinaries(prof *profile.Profile, g *graph.Graph, rx *regexp.Regex
|
|||
}
|
||||
}
|
||||
|
||||
f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset)
|
||||
f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol)
|
||||
if err != nil {
|
||||
fmt.Printf("%v\n", err)
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -744,7 +744,7 @@ func (sp *sourcePrinter) objectFile(m *profile.Mapping) plugin.ObjFile {
|
|||
if object, ok := sp.objects[m.File]; ok {
|
||||
return object // May be nil if we detected an error earlier.
|
||||
}
|
||||
object, err := sp.objectTool.Open(m.File, m.Start, m.Limit, m.Offset)
|
||||
object, err := sp.objectTool.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol)
|
||||
if err != nil {
|
||||
object = nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -325,7 +325,10 @@ func newMapping(prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, force b
|
|||
}
|
||||
|
||||
name := filepath.Base(m.File)
|
||||
f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ package profile
|
|||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (p *Profile) decoder() []decoder {
|
||||
|
|
@ -252,6 +253,14 @@ func (p *Profile) postDecode() error {
|
|||
} else {
|
||||
mappings[m.ID] = m
|
||||
}
|
||||
|
||||
// If this a main linux kernel mapping with a relocation symbol suffix
|
||||
// ("[kernel.kallsyms]_text"), extract said suffix.
|
||||
// It is fairly hacky to handle at this level, but the alternatives appear even worse.
|
||||
if strings.HasPrefix(m.File, "[kernel.kallsyms]") {
|
||||
m.KernelRelocationSymbol = strings.ReplaceAll(m.File, "[kernel.kallsyms]", "")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
functions := make(map[uint64]*Function, len(p.Function))
|
||||
|
|
|
|||
|
|
@ -303,16 +303,17 @@ func (pm *profileMerger) mapMapping(src *Mapping) mapInfo {
|
|||
return mi
|
||||
}
|
||||
m := &Mapping{
|
||||
ID: uint64(len(pm.p.Mapping) + 1),
|
||||
Start: src.Start,
|
||||
Limit: src.Limit,
|
||||
Offset: src.Offset,
|
||||
File: src.File,
|
||||
BuildID: src.BuildID,
|
||||
HasFunctions: src.HasFunctions,
|
||||
HasFilenames: src.HasFilenames,
|
||||
HasLineNumbers: src.HasLineNumbers,
|
||||
HasInlineFrames: src.HasInlineFrames,
|
||||
ID: uint64(len(pm.p.Mapping) + 1),
|
||||
Start: src.Start,
|
||||
Limit: src.Limit,
|
||||
Offset: src.Offset,
|
||||
File: src.File,
|
||||
KernelRelocationSymbol: src.KernelRelocationSymbol,
|
||||
BuildID: src.BuildID,
|
||||
HasFunctions: src.HasFunctions,
|
||||
HasFilenames: src.HasFilenames,
|
||||
HasLineNumbers: src.HasLineNumbers,
|
||||
HasInlineFrames: src.HasInlineFrames,
|
||||
}
|
||||
pm.p.Mapping = append(pm.p.Mapping, m)
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,15 @@ type Mapping struct {
|
|||
|
||||
fileX int64
|
||||
buildIDX int64
|
||||
|
||||
// Name of the kernel relocation symbol ("_text" or "_stext"), extracted from File.
|
||||
// For linux kernel mappings generated by some tools, correct symbolization depends
|
||||
// on knowing which of the two possible relocation symbols was used for `Start`.
|
||||
// This is given to us as a suffix in `File` (e.g. "[kernel.kallsyms]_stext").
|
||||
//
|
||||
// Note, this public field is not persisted in the proto. For the purposes of
|
||||
// copying / merging / hashing profiles, it is considered subsumed by `File`.
|
||||
KernelRelocationSymbol string
|
||||
}
|
||||
|
||||
// Location corresponds to Profile.Location
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
Copyright 2010-2017 Mike Bostock
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the author nor the names of contributors may be used to
|
||||
endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
# Building a customized D3.js bundle
|
||||
|
||||
The D3.js version distributed with pprof is customized to only include the modules required by pprof.
|
||||
|
||||
## Dependencies
|
||||
|
||||
First, it's necessary to pull all bundle dependencies. We will use a JavaScript package manager, [npm](https://www.npmjs.com/), to accomplish that. npm dependencies are declared in a `package.json` file, so create one with the following configuration:
|
||||
|
||||
```js
|
||||
{
|
||||
"name": "d3-pprof",
|
||||
"version": "1.0.0",
|
||||
"description": "A d3.js bundle for pprof.",
|
||||
"scripts": {
|
||||
"prepare": "rollup -c && uglifyjs d3.js -c -m -o d3.min.js"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"d3-selection": "1.1.0",
|
||||
"d3-hierarchy": "1.1.5",
|
||||
"d3-scale": "1.0.6",
|
||||
"d3-format": "1.2.0",
|
||||
"d3-ease": "1.0.3",
|
||||
"d3-array": "1.2.1",
|
||||
"d3-collection": "1.0.4",
|
||||
"d3-transition": "1.1.0",
|
||||
"rollup": "0.51.8",
|
||||
"rollup-plugin-node-resolve": "3",
|
||||
"uglify-js": "3.1.10"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Besides the bundle dependencies, the `package.json` file also specifies a script called `prepare`, which will be executed to create the bundle after `Rollup` is installed.
|
||||
|
||||
## Bundler
|
||||
|
||||
The simplest way of creating a custom bundle is to use a bundler, such as [Rollup](https://rollupjs.org/) or [Webpack](https://webpack.js.org/). Rollup will be used in this example.
|
||||
|
||||
First, create a `rollup.config.js` file, containing the configuration Rollup should use to build the bundle.
|
||||
|
||||
```js
|
||||
import node from "rollup-plugin-node-resolve";
|
||||
|
||||
export default {
|
||||
input: "index.js",
|
||||
output: {
|
||||
format: "umd",
|
||||
file: "d3.js"
|
||||
},
|
||||
name: "d3",
|
||||
plugins: [node()],
|
||||
sourcemap: false
|
||||
};
|
||||
```
|
||||
|
||||
Then create an `index.js` file containing all the functions that need to be exported in the bundle.
|
||||
|
||||
```js
|
||||
export {
|
||||
select,
|
||||
selection,
|
||||
event,
|
||||
} from "d3-selection";
|
||||
|
||||
export {
|
||||
hierarchy,
|
||||
partition,
|
||||
} from "d3-hierarchy";
|
||||
|
||||
export {
|
||||
scaleLinear,
|
||||
} from "d3-scale";
|
||||
|
||||
export {
|
||||
format,
|
||||
} from "d3-format";
|
||||
|
||||
export {
|
||||
easeCubic,
|
||||
} from "d3-ease";
|
||||
|
||||
export {
|
||||
ascending,
|
||||
} from "d3-array";
|
||||
|
||||
export {
|
||||
map,
|
||||
} from "d3-collection";
|
||||
|
||||
export {
|
||||
transition,
|
||||
} from "d3-transition";
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
Once all files were created, execute the following commands to pull all dependencies and build the bundle.
|
||||
|
||||
```
|
||||
% npm install
|
||||
% npm run prepare
|
||||
```
|
||||
|
||||
This will create two files, `d3.js` and `d3.min.js`, the custom D3.js bundle and its minified version respectively.
|
||||
|
||||
# References
|
||||
|
||||
## D3 Custom Bundle
|
||||
|
||||
A demonstration of building a custom D3 4.0 bundle using ES2015 modules and Rollup.
|
||||
|
||||
[bl.ocks.org/mbostock/bb09af4c39c79cffcde4](https://bl.ocks.org/mbostock/bb09af4c39c79cffcde4)
|
||||
|
||||
## d3-pprof
|
||||
|
||||
A repository containing all previously mentioned configuration files and the generated custom bundle.
|
||||
|
||||
[github.com/spiermar/d3-pprof](https://github.com/spiermar/d3-pprof)
|
||||
File diff suppressed because it is too large
Load Diff
13
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/D3_LICENSE
generated
vendored
Normal file
13
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/D3_LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
Copyright 2010-2021 Mike Bostock
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
33
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/README.md
generated
vendored
Normal file
33
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Building a customized D3.js bundle
|
||||
|
||||
The D3.js version distributed with pprof is customized to only include the
|
||||
modules required by pprof.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Install [npm](https://www.npmjs.com).
|
||||
|
||||
## Building
|
||||
|
||||
- Run `update.sh` to:
|
||||
- Download npm package dependencies (declared in `package.json` and `package-lock.json`)
|
||||
- Create a d3.js bundle containing the JavScript of d3 and d3-flame-graph (by running `webpack`)
|
||||
|
||||
This will `d3_flame_graph.go`, the minified custom D3.js bundle as Go source code.
|
||||
|
||||
# References / Appendix
|
||||
|
||||
## D3 Custom Bundle
|
||||
|
||||
A demonstration of building a custom D3 4.0 bundle using ES2015 modules and Rollup.
|
||||
|
||||
[bl.ocks.org/mbostock/bb09af4c39c79cffcde4](https://bl.ocks.org/mbostock/bb09af4c39c79cffcde4)
|
||||
|
||||
## Old version of d3-pprof
|
||||
|
||||
A previous verison of d3-flame-graph bundled for pprof used Rollup instead of
|
||||
Webpack. This has now been migrated directly into this directory.
|
||||
|
||||
The repository configuring Rollup was here:
|
||||
|
||||
[github.com/spiermar/d3-pprof](https://github.com/spiermar/d3-pprof)
|
||||
976
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/d3_flame_graph.go
generated
vendored
976
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/d3_flame_graph.go
generated
vendored
File diff suppressed because one or more lines are too long
13
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/index.js
generated
vendored
Normal file
13
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// This file exports a stripped-down API surface of d3 and d3-flame-graph,
|
||||
// using only the functions used by pprof.
|
||||
|
||||
export {
|
||||
select,
|
||||
} from "d3-selection";
|
||||
|
||||
export {
|
||||
default as flamegraph
|
||||
// If we export from "d3-flame-graph" that exports the "dist" version which
|
||||
// includes another copy of d3-selection. To avoid including d3-selection
|
||||
// twice in the output, instead import the "src" version.
|
||||
} from "d3-flame-graph/src/flamegraph";
|
||||
1106
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package-lock.json
generated
vendored
Normal file
1106
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
17
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package.json
generated
vendored
Normal file
17
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "d3-pprof",
|
||||
"version": "2.0.0",
|
||||
"description": "A d3.js bundle for pprof.",
|
||||
"scripts": {
|
||||
"prepare": "webpack --mode production"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"d3-flame-graph": "^4.1.3",
|
||||
"d3-selection": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"webpack": "^5.64.4",
|
||||
"webpack-cli": "^4.9.1"
|
||||
}
|
||||
}
|
||||
62
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/update.sh
generated
vendored
Normal file
62
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/update.sh
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Copyright 2021 Google Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
D3FLAMEGRAPH_CSS="d3-flamegraph.css"
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
generate_d3_flame_graph_go() {
|
||||
npm install
|
||||
# https://stackoverflow.com/a/21199041/171898
|
||||
local d3_js=$(cat d3.js | sed 's/`/`+"`"+`/g')
|
||||
local d3_css=$(cat "node_modules/d3-flame-graph/dist/${D3FLAMEGRAPH_CSS}")
|
||||
|
||||
cat <<-EOF > d3_flame_graph.go
|
||||
// D3.js is a JavaScript library for manipulating documents based on data.
|
||||
// https://github.com/d3/d3
|
||||
// See D3_LICENSE file for license details
|
||||
|
||||
// d3-flame-graph is a D3.js plugin that produces flame graphs from hierarchical data.
|
||||
// https://github.com/spiermar/d3-flame-graph
|
||||
// See D3_FLAME_GRAPH_LICENSE file for license details
|
||||
|
||||
package d3flamegraph
|
||||
|
||||
// JSSource returns the d3 and d3-flame-graph JavaScript bundle
|
||||
const JSSource = \`
|
||||
|
||||
$d3_js
|
||||
\`
|
||||
|
||||
// CSSSource returns the $D3FLAMEGRAPH_CSS file
|
||||
const CSSSource = \`
|
||||
$d3_css
|
||||
\`
|
||||
|
||||
EOF
|
||||
gofmt -w d3_flame_graph.go
|
||||
}
|
||||
|
||||
get_licenses() {
|
||||
cp node_modules/d3-selection/LICENSE D3_LICENSE
|
||||
cp node_modules/d3-flame-graph/LICENSE D3_FLAME_GRAPH_LICENSE
|
||||
}
|
||||
|
||||
get_licenses
|
||||
generate_d3_flame_graph_go
|
||||
13
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/webpack.config.js
generated
vendored
Normal file
13
src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/webpack.config.js
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Minimal webpack config to package a minified JS bundle (including
|
||||
// dependencies) for execution in a <script> tag in the browser.
|
||||
module.exports = {
|
||||
entry: './index.js',
|
||||
output: {
|
||||
path: __dirname, // Directory containing this webpack.config.js file.
|
||||
filename: 'd3.js',
|
||||
// Arbitrary; many module formats could be used, just keeping Universal
|
||||
// Module Definition as it's the same as what we used in a previous
|
||||
// version.
|
||||
libraryTarget: 'umd',
|
||||
},
|
||||
};
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# github.com/google/pprof v0.0.0-20211104044539-f987b9c94b31
|
||||
# github.com/google/pprof v0.0.0-20220314021825-5bba342933ea
|
||||
## explicit; go 1.14
|
||||
github.com/google/pprof/driver
|
||||
github.com/google/pprof/internal/binutils
|
||||
|
|
@ -12,7 +12,6 @@ github.com/google/pprof/internal/symbolizer
|
|||
github.com/google/pprof/internal/symbolz
|
||||
github.com/google/pprof/internal/transport
|
||||
github.com/google/pprof/profile
|
||||
github.com/google/pprof/third_party/d3
|
||||
github.com/google/pprof/third_party/d3flamegraph
|
||||
github.com/google/pprof/third_party/svgpan
|
||||
# github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d
|
||||
|
|
|
|||
Loading…
Reference in New Issue