|
@@ -734,57 +734,74 @@ func (ns Nodes) Sort(o NodeOrder) error {
|
734
|
734
|
case FlatNameOrder:
|
735
|
735
|
s = nodeSorter{ns,
|
736
|
736
|
func(l, r *Node) bool {
|
737
|
|
- if iv, jv := l.Flat, r.Flat; iv != jv {
|
738
|
|
- return abs64(iv) > abs64(jv)
|
|
737
|
+ if iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {
|
|
738
|
+ return iv > jv
|
739
|
739
|
}
|
740
|
|
- if l.Info.PrintableName() != r.Info.PrintableName() {
|
741
|
|
- return l.Info.PrintableName() < r.Info.PrintableName()
|
|
740
|
+ if iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {
|
|
741
|
+ return iv < jv
|
742
|
742
|
}
|
743
|
|
- iv, jv := l.Cum, r.Cum
|
744
|
|
- return abs64(iv) > abs64(jv)
|
|
743
|
+ if iv, jv := abs64(l.Cum), abs64(r.Cum); iv != jv {
|
|
744
|
+ return iv > jv
|
|
745
|
+ }
|
|
746
|
+ return compareNodes(l, r)
|
745
|
747
|
},
|
746
|
748
|
}
|
747
|
749
|
case FlatCumNameOrder:
|
748
|
750
|
s = nodeSorter{ns,
|
749
|
751
|
func(l, r *Node) bool {
|
750
|
|
- if iv, jv := l.Flat, r.Flat; iv != jv {
|
751
|
|
- return abs64(iv) > abs64(jv)
|
|
752
|
+ if iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {
|
|
753
|
+ return iv > jv
|
|
754
|
+ }
|
|
755
|
+ if iv, jv := abs64(l.Cum), abs64(r.Cum); iv != jv {
|
|
756
|
+ return iv > jv
|
752
|
757
|
}
|
753
|
|
- if iv, jv := l.Cum, r.Cum; iv != jv {
|
754
|
|
- return abs64(iv) > abs64(jv)
|
|
758
|
+ if iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {
|
|
759
|
+ return iv < jv
|
755
|
760
|
}
|
756
|
|
- return l.Info.PrintableName() < r.Info.PrintableName()
|
|
761
|
+ return compareNodes(l, r)
|
757
|
762
|
},
|
758
|
763
|
}
|
759
|
764
|
case NameOrder:
|
760
|
765
|
s = nodeSorter{ns,
|
761
|
766
|
func(l, r *Node) bool {
|
762
|
|
- return l.Info.Name < r.Info.Name
|
|
767
|
+ if iv, jv := l.Info.Name, r.Info.Name; iv != jv {
|
|
768
|
+ return iv < jv
|
|
769
|
+ }
|
|
770
|
+ return compareNodes(l, r)
|
763
|
771
|
},
|
764
|
772
|
}
|
765
|
773
|
case FileOrder:
|
766
|
774
|
s = nodeSorter{ns,
|
767
|
775
|
func(l, r *Node) bool {
|
768
|
|
- return l.Info.File < r.Info.File
|
|
776
|
+ if iv, jv := l.Info.File, r.Info.File; iv != jv {
|
|
777
|
+ return iv < jv
|
|
778
|
+ }
|
|
779
|
+ return compareNodes(l, r)
|
769
|
780
|
},
|
770
|
781
|
}
|
771
|
782
|
case AddressOrder:
|
772
|
783
|
s = nodeSorter{ns,
|
773
|
784
|
func(l, r *Node) bool {
|
774
|
|
- return l.Info.Address < r.Info.Address
|
|
785
|
+ if iv, jv := l.Info.Address, r.Info.Address; iv != jv {
|
|
786
|
+ return iv < jv
|
|
787
|
+ }
|
|
788
|
+ return compareNodes(l, r)
|
775
|
789
|
},
|
776
|
790
|
}
|
777
|
791
|
case CumNameOrder, EntropyOrder:
|
778
|
792
|
// Hold scoring for score-based ordering
|
779
|
793
|
var score map[*Node]int64
|
780
|
794
|
scoreOrder := func(l, r *Node) bool {
|
781
|
|
- if is, js := score[l], score[r]; is != js {
|
782
|
|
- return abs64(is) > abs64(js)
|
|
795
|
+ if iv, jv := abs64(score[l]), abs64(score[r]); iv != jv {
|
|
796
|
+ return iv > jv
|
|
797
|
+ }
|
|
798
|
+ if iv, jv := l.Info.PrintableName(), r.Info.PrintableName(); iv != jv {
|
|
799
|
+ return iv < jv
|
783
|
800
|
}
|
784
|
|
- if l.Info.PrintableName() != r.Info.PrintableName() {
|
785
|
|
- return l.Info.PrintableName() < r.Info.PrintableName()
|
|
801
|
+ if iv, jv := abs64(l.Flat), abs64(r.Flat); iv != jv {
|
|
802
|
+ return iv > jv
|
786
|
803
|
}
|
787
|
|
- return abs64(l.Flat) > abs64(r.Flat)
|
|
804
|
+ return compareNodes(l, r)
|
788
|
805
|
}
|
789
|
806
|
|
790
|
807
|
switch o {
|
|
@@ -808,6 +825,12 @@ func (ns Nodes) Sort(o NodeOrder) error {
|
808
|
825
|
return nil
|
809
|
826
|
}
|
810
|
827
|
|
|
828
|
+// compareNodes compares two nodes to provide a deterministic ordering
|
|
829
|
+// between them. Two nodes cannot have the same Node.Info value.
|
|
830
|
+func compareNodes(l, r *Node) bool {
|
|
831
|
+ return fmt.Sprint(l.Info) < fmt.Sprint(r.Info)
|
|
832
|
+}
|
|
833
|
+
|
811
|
834
|
// entropyScore computes a score for a node representing how important
|
812
|
835
|
// it is to include this node on a graph visualization. It is used to
|
813
|
836
|
// sort the nodes and select which ones to display if we have more
|