aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/vendor/github.com/google/pprof/internal/graph
diff options
context:
space:
mode:
authorHana (Hyang-Ah) Kim <hyangah@gmail.com>2018-11-06 17:48:08 -0500
committerHyang-Ah Hana Kim <hyangah@gmail.com>2018-11-07 12:27:21 +0000
commitc0a40e4fe5d4649672d0d430ca26551841fc4852 (patch)
tree4ccd82b68f0795d68bc43caff3cba7c9fabdb4d8 /src/cmd/vendor/github.com/google/pprof/internal/graph
parent1100df58238a1b1c55af148a880b48caf4be6504 (diff)
downloadgo-c0a40e4fe5d4649672d0d430ca26551841fc4852.tar.xz
cmd/vendor: update github.com/google/pprof
Sync @ fde099a (Oct 26, 2018) Also update misc/nacl/testzip.proto to include new testdata. Change-Id: If41590be9f395a591056e89a417b589c4ba71b1a Reviewed-on: https://go-review.googlesource.com/c/147979 Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/cmd/vendor/github.com/google/pprof/internal/graph')
-rw-r--r--src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go1
-rw-r--r--src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go29
-rw-r--r--src/cmd/vendor/github.com/google/pprof/internal/graph/graph_test.go157
3 files changed, 180 insertions, 7 deletions
diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go
index f3721e92f5..09debfb007 100644
--- a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go
+++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go
@@ -382,6 +382,7 @@ func dotColor(score float64, isBackground bool) string {
func multilinePrintableName(info *NodeInfo) string {
infoCopy := *info
+ infoCopy.Name = ShortenFunctionName(infoCopy.Name)
infoCopy.Name = strings.Replace(infoCopy.Name, "::", `\n`, -1)
infoCopy.Name = strings.Replace(infoCopy.Name, ".", `\n`, -1)
if infoCopy.File != "" {
diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go
index cd72bf2ab1..aebd1bf0e8 100644
--- a/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go
+++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/graph.go
@@ -19,6 +19,7 @@ import (
"fmt"
"math"
"path/filepath"
+ "regexp"
"sort"
"strconv"
"strings"
@@ -26,6 +27,12 @@ import (
"github.com/google/pprof/profile"
)
+var (
+ javaRegExp = regexp.MustCompile(`^(?:[a-z]\w*\.)*([A-Z][\w\$]*\.(?:<init>|[a-z]\w*(?:\$\d+)?))(?:(?:\()|$)`)
+ goRegExp = regexp.MustCompile(`^(?:[\w\-\.]+\/)+(.+)`)
+ cppRegExp = regexp.MustCompile(`^(?:(?:\(anonymous namespace\)::)(\w+$))|(?:(?:\(anonymous namespace\)::)?(?:[_a-zA-Z]\w*\::|)*(_*[A-Z]\w*::~?[_a-zA-Z]\w*)$)`)
+)
+
// Graph summarizes a performance profile into a format that is
// suitable for visualization.
type Graph struct {
@@ -420,6 +427,16 @@ func newTree(prof *profile.Profile, o *Options) (g *Graph) {
return selectNodesForGraph(nodes, o.DropNegative)
}
+// ShortenFunctionName returns a shortened version of a function's name.
+func ShortenFunctionName(f string) string {
+ for _, re := range []*regexp.Regexp{goRegExp, javaRegExp, cppRegExp} {
+ if matches := re.FindStringSubmatch(f); len(matches) >= 2 {
+ return strings.Join(matches[1:], "")
+ }
+ }
+ return f
+}
+
// TrimTree trims a Graph in forest form, keeping only the nodes in kept. This
// will not work correctly if even a single node has multiple parents.
func (g *Graph) TrimTree(kept NodePtrSet) {
@@ -512,9 +529,7 @@ func isNegative(n *Node) bool {
// CreateNodes creates graph nodes for all locations in a profile. It
// returns set of all nodes, plus a mapping of each location to the
-// set of corresponding nodes (one per location.Line). If kept is
-// non-nil, only nodes in that set are included; nodes that do not
-// match are represented as a nil.
+// set of corresponding nodes (one per location.Line).
func CreateNodes(prof *profile.Profile, o *Options) (Nodes, map[uint64]Nodes) {
locations := make(map[uint64]Nodes, len(prof.Location))
nm := make(NodeMap, len(prof.Location))
@@ -564,13 +579,13 @@ func nodeInfo(l *profile.Location, line profile.Line, objfile string, o *Options
if fname := line.Function.Filename; fname != "" {
ni.File = filepath.Clean(fname)
}
- if o.ObjNames {
- ni.Objfile = objfile
- ni.StartLine = int(line.Function.StartLine)
- }
if o.OrigFnNames {
ni.OrigName = line.Function.SystemName
}
+ if o.ObjNames || (ni.Name == "" && ni.OrigName == "") {
+ ni.Objfile = objfile
+ ni.StartLine = int(line.Function.StartLine)
+ }
return ni
}
diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/graph_test.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/graph_test.go
index 5657084cac..ef1171a14d 100644
--- a/src/cmd/vendor/github.com/google/pprof/internal/graph/graph_test.go
+++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/graph_test.go
@@ -3,6 +3,8 @@ package graph
import (
"fmt"
"testing"
+
+ "github.com/google/pprof/profile"
)
func edgeDebugString(edge *Edge) string {
@@ -312,3 +314,158 @@ func TestTrimTree(t *testing.T) {
}
}
}
+
+func nodeTestProfile() *profile.Profile {
+ mappings := []*profile.Mapping{
+ {
+ ID: 1,
+ File: "symbolized_binary",
+ },
+ {
+ ID: 2,
+ File: "unsymbolized_library_1",
+ },
+ {
+ ID: 3,
+ File: "unsymbolized_library_2",
+ },
+ }
+ functions := []*profile.Function{
+ {ID: 1, Name: "symname"},
+ {ID: 2},
+ }
+ locations := []*profile.Location{
+ {
+ ID: 1,
+ Mapping: mappings[0],
+ Line: []profile.Line{
+ {Function: functions[0]},
+ },
+ },
+ {
+ ID: 2,
+ Mapping: mappings[1],
+ Line: []profile.Line{
+ {Function: functions[1]},
+ },
+ },
+ {
+ ID: 3,
+ Mapping: mappings[2],
+ },
+ }
+ return &profile.Profile{
+ PeriodType: &profile.ValueType{Type: "cpu", Unit: "milliseconds"},
+ SampleType: []*profile.ValueType{
+ {Type: "type", Unit: "unit"},
+ },
+ Sample: []*profile.Sample{
+ {
+ Location: []*profile.Location{locations[0]},
+ Value: []int64{1},
+ },
+ {
+ Location: []*profile.Location{locations[1]},
+ Value: []int64{1},
+ },
+ {
+ Location: []*profile.Location{locations[2]},
+ Value: []int64{1},
+ },
+ },
+ Location: locations,
+ Function: functions,
+ Mapping: mappings,
+ }
+}
+
+// Check that nodes are properly created for a simple profile.
+func TestCreateNodes(t *testing.T) {
+ testProfile := nodeTestProfile()
+ wantNodeSet := NodeSet{
+ {Name: "symname"}: true,
+ {Objfile: "unsymbolized_library_1"}: true,
+ {Objfile: "unsymbolized_library_2"}: true,
+ }
+
+ nodes, _ := CreateNodes(testProfile, &Options{})
+ if len(nodes) != len(wantNodeSet) {
+ t.Errorf("got %d nodes, want %d", len(nodes), len(wantNodeSet))
+ }
+ for _, node := range nodes {
+ if !wantNodeSet[node.Info] {
+ t.Errorf("unexpected node %v", node.Info)
+ }
+ }
+}
+
+func TestShortenFunctionName(t *testing.T) {
+ type testCase struct {
+ name string
+ want string
+ }
+ testcases := []testCase{
+ {
+ "root",
+ "root",
+ },
+ {
+ "syscall.Syscall",
+ "syscall.Syscall",
+ },
+ {
+ "net/http.(*conn).serve",
+ "http.(*conn).serve",
+ },
+ {
+ "github.com/blahBlah/foo.Foo",
+ "foo.Foo",
+ },
+ {
+ "github.com/BlahBlah/foo.Foo",
+ "foo.Foo",
+ },
+ {
+ "github.com/blah-blah/foo_bar.(*FooBar).Foo",
+ "foo_bar.(*FooBar).Foo",
+ },
+ {
+ "encoding/json.(*structEncoder).(encoding/json.encode)-fm",
+ "json.(*structEncoder).(encoding/json.encode)-fm",
+ },
+ {
+ "github.com/blah/blah/vendor/gopkg.in/redis.v3.(*baseClient).(github.com/blah/blah/vendor/gopkg.in/redis.v3.process)-fm",
+ "redis.v3.(*baseClient).(github.com/blah/blah/vendor/gopkg.in/redis.v3.process)-fm",
+ },
+ {
+ "java.util.concurrent.ThreadPoolExecutor$Worker.run",
+ "ThreadPoolExecutor$Worker.run",
+ },
+ {
+ "java.bar.foo.FooBar.run(java.lang.Runnable)",
+ "FooBar.run",
+ },
+ {
+ "(anonymous namespace)::Bar::Foo",
+ "Bar::Foo",
+ },
+ {
+ "(anonymous namespace)::foo",
+ "foo",
+ },
+ {
+ "foo_bar::Foo::bar",
+ "Foo::bar",
+ },
+ {
+ "foo",
+ "foo",
+ },
+ }
+ for _, tc := range testcases {
+ name := ShortenFunctionName(tc.name)
+ if got, want := name, tc.want; got != want {
+ t.Errorf("ShortenFunctionName(%q) = %q, want %q", tc.name, got, want)
+ }
+ }
+}