diff options
| author | Hana (Hyang-Ah) Kim <hyangah@gmail.com> | 2018-11-06 17:48:08 -0500 |
|---|---|---|
| committer | Hyang-Ah Hana Kim <hyangah@gmail.com> | 2018-11-07 12:27:21 +0000 |
| commit | c0a40e4fe5d4649672d0d430ca26551841fc4852 (patch) | |
| tree | 4ccd82b68f0795d68bc43caff3cba7c9fabdb4d8 /src/cmd/vendor/github.com/google/pprof/internal/graph | |
| parent | 1100df58238a1b1c55af148a880b48caf4be6504 (diff) | |
| download | go-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')
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) + } + } +} |
