|
@@ -288,39 +288,39 @@ func newTree(prof *profile.Profile, o *Options) (g *Graph) {
|
288
|
288
|
kept := o.KeptNodes
|
289
|
289
|
keepBinary := o.ObjNames
|
290
|
290
|
parentNodeMap := make(map[*Node]NodeMap, len(prof.Sample))
|
|
291
|
+nextSample:
|
291
|
292
|
for _, sample := range prof.Sample {
|
292
|
293
|
weight := o.SampleValue(sample.Value)
|
293
|
294
|
if weight == 0 {
|
294
|
295
|
continue
|
295
|
296
|
}
|
296
|
297
|
var parent *Node
|
297
|
|
- // A residual edge goes over one or more nodes that were not kept.
|
298
|
|
- residual := false
|
299
|
298
|
labels := joinLabels(sample)
|
300
|
299
|
// Group the sample frames, based on a per-node map.
|
301
|
300
|
for i := len(sample.Location) - 1; i >= 0; i-- {
|
302
|
301
|
l := sample.Location[i]
|
303
|
|
- nodeMap := parentNodeMap[parent]
|
304
|
|
- if nodeMap == nil {
|
305
|
|
- nodeMap = make(NodeMap)
|
306
|
|
- parentNodeMap[parent] = nodeMap
|
|
302
|
+ lines := l.Line
|
|
303
|
+ if len(lines) == 0 {
|
|
304
|
+ lines = []profile.Line{{}} // Create empty line to include location info.
|
307
|
305
|
}
|
308
|
|
- locNodes := nodeMap.findOrInsertLocation(l, keepBinary, kept)
|
309
|
|
- for ni := len(locNodes) - 1; ni >= 0; ni-- {
|
310
|
|
- n := locNodes[ni]
|
|
306
|
+ for lidx := len(lines) - 1; lidx >= 0; lidx-- {
|
|
307
|
+ nodeMap := parentNodeMap[parent]
|
|
308
|
+ if nodeMap == nil {
|
|
309
|
+ nodeMap = make(NodeMap)
|
|
310
|
+ parentNodeMap[parent] = nodeMap
|
|
311
|
+ }
|
|
312
|
+ n := nodeMap.findOrInsertLine(l, lines[lidx], keepBinary, kept)
|
311
|
313
|
if n == nil {
|
312
|
|
- residual = true
|
313
|
|
- continue
|
|
314
|
+ continue nextSample
|
314
|
315
|
}
|
315
|
316
|
n.addSample(weight, labels, sample.NumLabel, o.FormatTag, false)
|
316
|
317
|
if parent != nil {
|
317
|
|
- parent.AddToEdge(n, weight, residual, ni != len(locNodes)-1)
|
|
318
|
+ parent.AddToEdge(n, weight, false, lidx != len(lines)-1)
|
318
|
319
|
}
|
319
|
320
|
parent = n
|
320
|
|
- residual = false
|
321
|
321
|
}
|
322
|
322
|
}
|
323
|
|
- if parent != nil && !residual {
|
|
323
|
+ if parent != nil {
|
324
|
324
|
parent.addSample(weight, labels, sample.NumLabel, o.FormatTag, true)
|
325
|
325
|
}
|
326
|
326
|
}
|
|
@@ -395,9 +395,15 @@ func CreateNodes(prof *profile.Profile, keepBinary bool, kept NodeSet) (Nodes, m
|
395
|
395
|
|
396
|
396
|
nm := make(NodeMap, len(prof.Location))
|
397
|
397
|
for _, l := range prof.Location {
|
398
|
|
- if nodes := nm.findOrInsertLocation(l, keepBinary, kept); nodes != nil {
|
399
|
|
- locations[l.ID] = nodes
|
|
398
|
+ lines := l.Line
|
|
399
|
+ if len(lines) == 0 {
|
|
400
|
+ lines = []profile.Line{{}} // Create empty line to include location info.
|
400
|
401
|
}
|
|
402
|
+ nodes := make(Nodes, len(lines))
|
|
403
|
+ for ln := range lines {
|
|
404
|
+ nodes[ln] = nm.findOrInsertLine(l, lines[ln], keepBinary, kept)
|
|
405
|
+ }
|
|
406
|
+ locations[l.ID] = nodes
|
401
|
407
|
}
|
402
|
408
|
return nm.nodes(), locations
|
403
|
409
|
}
|
|
@@ -410,51 +416,33 @@ func (nm NodeMap) nodes() Nodes {
|
410
|
416
|
return nodes
|
411
|
417
|
}
|
412
|
418
|
|
413
|
|
-func (nm NodeMap) findOrInsertLocation(l *profile.Location, keepBinary bool, kept NodeSet) Nodes {
|
|
419
|
+func (nm NodeMap) findOrInsertLine(l *profile.Location, li profile.Line, keepBinary bool, kept NodeSet) *Node {
|
414
|
420
|
var objfile string
|
415
|
421
|
if m := l.Mapping; m != nil && m.File != "" {
|
416
|
422
|
objfile = filepath.Base(m.File)
|
417
|
423
|
}
|
418
|
424
|
|
419
|
|
- if len(l.Line) == 0 {
|
420
|
|
- ni := NodeInfo{
|
421
|
|
- Address: l.Address,
|
422
|
|
- Objfile: objfile,
|
423
|
|
- }
|
424
|
|
- return Nodes{nm.FindOrInsertNode(ni, kept)}
|
|
425
|
+ if ni := nodeInfo(l, li, objfile, keepBinary); ni != nil {
|
|
426
|
+ return nm.FindOrInsertNode(*ni, kept)
|
425
|
427
|
}
|
426
|
|
- locNodes := make(Nodes, len(l.Line))
|
427
|
|
- for li := range l.Line {
|
428
|
|
- if ni := nodeInfo(l, li, objfile, keepBinary); ni != nil {
|
429
|
|
- locNodes[li] = nm.FindOrInsertNode(*ni, kept)
|
430
|
|
- }
|
431
|
|
- }
|
432
|
|
- return locNodes
|
|
428
|
+ return nil
|
433
|
429
|
}
|
434
|
430
|
|
435
|
|
-func nodeInfo(l *profile.Location, li int, objfile string, keepBinary bool) *NodeInfo {
|
436
|
|
- if !keepBinary {
|
437
|
|
- objfile = ""
|
438
|
|
- }
|
439
|
|
- line := l.Line[li]
|
|
431
|
+func nodeInfo(l *profile.Location, line profile.Line, objfile string, keepBinary bool) *NodeInfo {
|
440
|
432
|
if line.Function == nil {
|
441
|
|
- if l.Address == 0 {
|
442
|
|
- return nil
|
443
|
|
- }
|
444
|
433
|
return &NodeInfo{Address: l.Address, Objfile: objfile}
|
445
|
434
|
}
|
446
|
|
-
|
447
|
435
|
ni := &NodeInfo{
|
448
|
436
|
Address: l.Address,
|
449
|
437
|
Lineno: int(line.Line),
|
450
|
438
|
Name: line.Function.Name,
|
451
|
439
|
OrigName: line.Function.SystemName,
|
452
|
|
- Objfile: objfile,
|
453
|
440
|
}
|
454
|
441
|
if fname := line.Function.Filename; fname != "" {
|
455
|
442
|
ni.File = filepath.Clean(fname)
|
456
|
443
|
}
|
457
|
444
|
if keepBinary {
|
|
445
|
+ ni.Objfile = objfile
|
458
|
446
|
ni.StartLine = int(line.Function.StartLine)
|
459
|
447
|
}
|
460
|
448
|
return ni
|
|
@@ -479,7 +467,7 @@ func (t tags) Less(i, j int) bool {
|
479
|
467
|
return t.t[i].Name < t.t[j].Name
|
480
|
468
|
}
|
481
|
469
|
|
482
|
|
-// Sum adds the Flat and sum values on a report.
|
|
470
|
+// Sum adds the flat and cum values of a set of nodes.
|
483
|
471
|
func (ns Nodes) Sum() (flat int64, cum int64) {
|
484
|
472
|
for _, n := range ns {
|
485
|
473
|
flat += n.Flat
|