|
@@ -143,17 +143,16 @@ func (i *NodeInfo) NameComponents() []string {
|
143
|
143
|
type NodeMap map[NodeInfo]*Node
|
144
|
144
|
|
145
|
145
|
// NodeSet maps is a collection of node info structs.
|
146
|
|
-type NodeSet struct {
|
147
|
|
- Info map[NodeInfo]bool
|
148
|
|
- Ptr map[*Node]bool
|
149
|
|
-}
|
|
146
|
+type NodeSet map[NodeInfo]bool
|
|
147
|
+
|
|
148
|
+type nodePtrSet map[*Node]bool
|
150
|
149
|
|
151
|
150
|
// FindOrInsertNode takes the info for a node and either returns a matching node
|
152
|
151
|
// from the node map if one exists, or adds one to the map if one does not.
|
153
|
152
|
// If kept is non-nil, nodes are only added if they can be located on it.
|
154
|
153
|
func (nm NodeMap) FindOrInsertNode(info NodeInfo, kept NodeSet) *Node {
|
155
|
|
- if kept.Info != nil {
|
156
|
|
- if _, ok := kept.Info[info]; !ok {
|
|
154
|
+ if kept != nil {
|
|
155
|
+ if _, ok := kept[info]; !ok {
|
157
|
156
|
return nil
|
158
|
157
|
}
|
159
|
158
|
}
|
|
@@ -337,10 +336,10 @@ func newTree(prof *profile.Profile, o *Options) (g *Graph) {
|
337
|
336
|
|
338
|
337
|
// Trims a Graph that is in forest form to contain only the nodes in kept. This
|
339
|
338
|
// will not work correctly in the case that a node has multiple parents.
|
340
|
|
-func (g *Graph) TrimTree(kept NodeSet) {
|
|
339
|
+func (g *Graph) TrimTree(kept nodePtrSet) {
|
341
|
340
|
// Creates a new list of nodes
|
342
|
341
|
oldNodes := g.Nodes
|
343
|
|
- g.Nodes = make(Nodes, 0, len(kept.Ptr))
|
|
342
|
+ g.Nodes = make(Nodes, 0, len(kept))
|
344
|
343
|
|
345
|
344
|
for _, cur := range oldNodes {
|
346
|
345
|
// A node may not have multiple parents
|
|
@@ -349,7 +348,7 @@ func (g *Graph) TrimTree(kept NodeSet) {
|
349
|
348
|
}
|
350
|
349
|
|
351
|
350
|
// If a node should be kept, add it to the next list of nodes
|
352
|
|
- if _, ok := kept.Ptr[cur]; ok {
|
|
351
|
+ if _, ok := kept[cur]; ok {
|
353
|
352
|
g.Nodes = append(g.Nodes, cur)
|
354
|
353
|
continue
|
355
|
354
|
}
|
|
@@ -600,19 +599,36 @@ func (g *Graph) DiscardLowFrequencyNodes(nodeCutoff int64) NodeSet {
|
600
|
599
|
return makeNodeSet(g.Nodes, nodeCutoff)
|
601
|
600
|
}
|
602
|
601
|
|
|
602
|
+// discardLowFrequencyNodePtrs returns a NodePtrSet of nodes at or over a
|
|
603
|
+// specific cum value cutoff.
|
|
604
|
+func (g *Graph) DiscardLowFrequencyNodePtrs(nodeCutoff int64) nodePtrSet {
|
|
605
|
+ cutNodes := getNodesWithCumCutoff(g.Nodes, nodeCutoff)
|
|
606
|
+ kept := make(nodePtrSet, len(cutNodes))
|
|
607
|
+ for _, n := range cutNodes {
|
|
608
|
+ kept[n] = true
|
|
609
|
+ }
|
|
610
|
+ return kept
|
|
611
|
+}
|
|
612
|
+
|
603
|
613
|
func makeNodeSet(nodes Nodes, nodeCutoff int64) NodeSet {
|
604
|
|
- kept := NodeSet{
|
605
|
|
- Info: make(map[NodeInfo]bool, len(nodes)),
|
606
|
|
- Ptr: make(map[*Node]bool, len(nodes)),
|
|
614
|
+ cutNodes := getNodesWithCumCutoff(nodes, nodeCutoff)
|
|
615
|
+ kept := make(NodeSet, len(cutNodes))
|
|
616
|
+ for _, n := range cutNodes {
|
|
617
|
+ kept[n.Info] = true
|
607
|
618
|
}
|
|
619
|
+ return kept
|
|
620
|
+}
|
|
621
|
+
|
|
622
|
+// Returns all the nodes who have a Cum value greater than or equal to cutoff
|
|
623
|
+func getNodesWithCumCutoff(nodes Nodes, nodeCutoff int64) Nodes {
|
|
624
|
+ cutoffNodes := make(Nodes, 0, len(nodes))
|
608
|
625
|
for _, n := range nodes {
|
609
|
626
|
if abs64(n.Cum) < nodeCutoff {
|
610
|
627
|
continue
|
611
|
628
|
}
|
612
|
|
- kept.Info[n.Info] = true
|
613
|
|
- kept.Ptr[n] = true
|
|
629
|
+ cutoffNodes = append(cutoffNodes, n)
|
614
|
630
|
}
|
615
|
|
- return kept
|
|
631
|
+ return cutoffNodes
|
616
|
632
|
}
|
617
|
633
|
|
618
|
634
|
// TrimLowFrequencyTags removes tags that have less than
|
|
@@ -667,8 +683,22 @@ func (g *Graph) SortNodes(cum bool, visualMode bool) {
|
667
|
683
|
}
|
668
|
684
|
}
|
669
|
685
|
|
|
686
|
+// selectTopNodePtrs returns a set of the top maxNodes *Node in a graph.
|
|
687
|
+func (g *Graph) SelectTopNodePtrs(maxNodes int, visualMode bool) nodePtrSet {
|
|
688
|
+ set := make(nodePtrSet)
|
|
689
|
+ for _, node := range g.selectTopNodes(maxNodes, visualMode) {
|
|
690
|
+ set[node] = true
|
|
691
|
+ }
|
|
692
|
+ return set
|
|
693
|
+}
|
|
694
|
+
|
670
|
695
|
// SelectTopNodes returns a set of the top maxNodes nodes in a graph.
|
671
|
696
|
func (g *Graph) SelectTopNodes(maxNodes int, visualMode bool) NodeSet {
|
|
697
|
+ return makeNodeSet(g.selectTopNodes(maxNodes, visualMode), 0)
|
|
698
|
+}
|
|
699
|
+
|
|
700
|
+// selectTopNodes returns a slice of the top maxNodes nodes in a graph
|
|
701
|
+func (g *Graph) selectTopNodes(maxNodes int, visualMode bool) Nodes {
|
672
|
702
|
if maxNodes > 0 {
|
673
|
703
|
if visualMode {
|
674
|
704
|
var count int
|
|
@@ -685,7 +715,7 @@ func (g *Graph) SelectTopNodes(maxNodes int, visualMode bool) NodeSet {
|
685
|
715
|
if maxNodes > len(g.Nodes) {
|
686
|
716
|
maxNodes = len(g.Nodes)
|
687
|
717
|
}
|
688
|
|
- return makeNodeSet(g.Nodes[:maxNodes], 0)
|
|
718
|
+ return g.Nodes[:maxNodes]
|
689
|
719
|
}
|
690
|
720
|
|
691
|
721
|
// countTags counts the tags with flat count. This underestimates the
|