|
@@ -20,6 +20,7 @@ import (
|
20
|
20
|
"math"
|
21
|
21
|
"path/filepath"
|
22
|
22
|
"sort"
|
|
23
|
+ "strconv"
|
23
|
24
|
"strings"
|
24
|
25
|
|
25
|
26
|
"github.com/google/pprof/profile"
|
|
@@ -156,8 +157,10 @@ type NodeSet map[NodeInfo]bool
|
156
|
157
|
// If parent is non-nil, return a match with the same parent.
|
157
|
158
|
// If kept is non-nil, nodes are only added if they can be located on it.
|
158
|
159
|
func (m NodeMap) FindOrInsertNode(info NodeInfo, parent *Node, kept NodeSet) *Node {
|
159
|
|
- if kept != nil && !kept[info] {
|
160
|
|
- return nil
|
|
160
|
+ if kept != nil {
|
|
161
|
+ if _, ok := kept[info]; !ok {
|
|
162
|
+ return nil
|
|
163
|
+ }
|
161
|
164
|
}
|
162
|
165
|
|
163
|
166
|
extendedInfo := ExtendedNodeInfo{
|
|
@@ -165,7 +168,7 @@ func (m NodeMap) FindOrInsertNode(info NodeInfo, parent *Node, kept NodeSet) *No
|
165
|
168
|
parent,
|
166
|
169
|
}
|
167
|
170
|
|
168
|
|
- if n := m[extendedInfo]; n != nil {
|
|
171
|
+ if n, ok := m[extendedInfo]; ok {
|
169
|
172
|
return n
|
170
|
173
|
}
|
171
|
174
|
|
|
@@ -216,8 +219,9 @@ func SortTags(t []*Tag, flat bool) []*Tag {
|
216
|
219
|
|
217
|
220
|
// New summarizes performance data from a profile into a graph.
|
218
|
221
|
func New(prof *profile.Profile, o *Options) (g *Graph) {
|
|
222
|
+ const averageNodesPerLocation = 2
|
219
|
223
|
locations := NewLocInfo(prof, o.ObjNames)
|
220
|
|
- nm := make(NodeMap)
|
|
224
|
+ nm := make(NodeMap, len(prof.Location)*averageNodesPerLocation)
|
221
|
225
|
for _, sample := range prof.Sample {
|
222
|
226
|
if sample.Location == nil {
|
223
|
227
|
continue
|
|
@@ -227,8 +231,8 @@ func New(prof *profile.Profile, o *Options) (g *Graph) {
|
227
|
231
|
// Keep track of the index on the Sample for each frame,
|
228
|
232
|
// to determine inlining status.
|
229
|
233
|
|
230
|
|
- var stack []NodeInfo
|
231
|
|
- var locIndex []int
|
|
234
|
+ stack := make([]NodeInfo, 0, len(sample.Location))
|
|
235
|
+ locIndex := make([]int, 0, len(sample.Location)*averageNodesPerLocation)
|
232
|
236
|
for i, loc := range sample.Location {
|
233
|
237
|
id := loc.ID
|
234
|
238
|
stack = append(stack, locations[id]...)
|
|
@@ -238,7 +242,8 @@ func New(prof *profile.Profile, o *Options) (g *Graph) {
|
238
|
242
|
}
|
239
|
243
|
|
240
|
244
|
weight := o.SampleValue(sample.Value)
|
241
|
|
- seenEdge := make(map[*Node]map[*Node]bool)
|
|
245
|
+ seenNode := make(map[*Node]bool, len(stack))
|
|
246
|
+ seenEdge := make(map[nodePair]bool, len(stack))
|
242
|
247
|
var nn *Node
|
243
|
248
|
nlocIndex := -1
|
244
|
249
|
residual := false
|
|
@@ -259,13 +264,13 @@ func New(prof *profile.Profile, o *Options) (g *Graph) {
|
259
|
264
|
n.addSample(sample, weight, o.FormatTag, true)
|
260
|
265
|
}
|
261
|
266
|
// Add cum weight to all nodes in stack, avoiding double counting.
|
262
|
|
- if seenEdge[n] == nil {
|
263
|
|
- seenEdge[n] = make(map[*Node]bool)
|
|
267
|
+ if _, ok := seenNode[n]; !ok {
|
|
268
|
+ seenNode[n] = true
|
264
|
269
|
n.addSample(sample, weight, o.FormatTag, false)
|
265
|
270
|
}
|
266
|
271
|
// Update edge weights for all edges in stack, avoiding double counting.
|
267
|
|
- if nn != nil && n != nn && !seenEdge[n][nn] {
|
268
|
|
- seenEdge[n][nn] = true
|
|
272
|
+ if _, ok := seenEdge[nodePair{n, nn}]; !ok && nn != nil && n != nn {
|
|
273
|
+ seenEdge[nodePair{n, nn}] = true
|
269
|
274
|
// This is an inlined edge if the caller and the callee
|
270
|
275
|
// correspond to the same entry in the sample.
|
271
|
276
|
nn.BumpWeight(n, weight, residual, locIndex[i-1] == nlocIndex)
|
|
@@ -288,6 +293,10 @@ func New(prof *profile.Profile, o *Options) (g *Graph) {
|
288
|
293
|
return &Graph{ns}
|
289
|
294
|
}
|
290
|
295
|
|
|
296
|
+type nodePair struct {
|
|
297
|
+ src, dest *Node
|
|
298
|
+}
|
|
299
|
+
|
291
|
300
|
// isNegative returns true if the node is considered as "negative" for the
|
292
|
301
|
// purposes of drop_negative.
|
293
|
302
|
func isNegative(n *Node) bool {
|
|
@@ -409,15 +418,12 @@ func (n *Node) addSample(s *profile.Sample, value int64, format func(int64, stri
|
409
|
418
|
n.NumericTags[joinedLabels] = numericTags
|
410
|
419
|
}
|
411
|
420
|
// Add numeric tags
|
|
421
|
+ if format == nil {
|
|
422
|
+ format = defaultLabelFormat
|
|
423
|
+ }
|
412
|
424
|
for key, nvals := range s.NumLabel {
|
413
|
425
|
for _, v := range nvals {
|
414
|
|
- var label string
|
415
|
|
- if format != nil {
|
416
|
|
- label = format(v, key)
|
417
|
|
- } else {
|
418
|
|
- label = fmt.Sprintf("%d", v)
|
419
|
|
- }
|
420
|
|
- t := numericTags.findOrAddTag(label, key, v)
|
|
426
|
+ t := numericTags.findOrAddTag(format(v, key), key, v)
|
421
|
427
|
if flat {
|
422
|
428
|
t.Flat += value
|
423
|
429
|
} else {
|
|
@@ -427,6 +433,10 @@ func (n *Node) addSample(s *profile.Sample, value int64, format func(int64, stri
|
427
|
433
|
}
|
428
|
434
|
}
|
429
|
435
|
|
|
436
|
+func defaultLabelFormat(v int64, key string) string {
|
|
437
|
+ return strconv.FormatInt(v, 10)
|
|
438
|
+}
|
|
439
|
+
|
430
|
440
|
func (m TagMap) findOrAddTag(label, unit string, value int64) *Tag {
|
431
|
441
|
l := m[label]
|
432
|
442
|
if l == nil {
|