@@ -607,29 +607,24 @@ static void init_rem_hits(void)
607
607
rem_hits .ms .sym = rem_sq_bracket ;
608
608
}
609
609
610
- static size_t __callchain__fprintf_graph (FILE * fp , struct callchain_node * self ,
610
+ static size_t __callchain__fprintf_graph (FILE * fp , struct rb_root * root ,
611
611
u64 total_samples , int depth ,
612
612
int depth_mask , int left_margin )
613
613
{
614
614
struct rb_node * node , * next ;
615
615
struct callchain_node * child ;
616
616
struct callchain_list * chain ;
617
617
int new_depth_mask = depth_mask ;
618
- u64 new_total ;
619
618
u64 remaining ;
620
619
size_t ret = 0 ;
621
620
int i ;
622
621
uint entries_printed = 0 ;
623
622
624
- if (callchain_param .mode == CHAIN_GRAPH_REL )
625
- new_total = self -> children_hit ;
626
- else
627
- new_total = total_samples ;
628
-
629
- remaining = new_total ;
623
+ remaining = total_samples ;
630
624
631
- node = rb_first (& self -> rb_root );
625
+ node = rb_first (root );
632
626
while (node ) {
627
+ u64 new_total ;
633
628
u64 cumul ;
634
629
635
630
child = rb_entry (node , struct callchain_node , rb_node );
@@ -657,11 +652,17 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
657
652
list_for_each_entry (chain , & child -> val , list ) {
658
653
ret += ipchain__fprintf_graph (fp , chain , depth ,
659
654
new_depth_mask , i ++ ,
660
- new_total ,
655
+ total_samples ,
661
656
cumul ,
662
657
left_margin );
663
658
}
664
- ret += __callchain__fprintf_graph (fp , child , new_total ,
659
+
660
+ if (callchain_param .mode == CHAIN_GRAPH_REL )
661
+ new_total = child -> children_hit ;
662
+ else
663
+ new_total = total_samples ;
664
+
665
+ ret += __callchain__fprintf_graph (fp , & child -> rb_root , new_total ,
665
666
depth + 1 ,
666
667
new_depth_mask | (1 << depth ),
667
668
left_margin );
@@ -671,69 +672,83 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
671
672
}
672
673
673
674
if (callchain_param .mode == CHAIN_GRAPH_REL &&
674
- remaining && remaining != new_total ) {
675
+ remaining && remaining != total_samples ) {
675
676
676
677
if (!rem_sq_bracket )
677
678
return ret ;
678
679
679
680
new_depth_mask &= ~(1 << (depth - 1 ));
680
-
681
681
ret += ipchain__fprintf_graph (fp , & rem_hits , depth ,
682
- new_depth_mask , 0 , new_total ,
682
+ new_depth_mask , 0 , total_samples ,
683
683
remaining , left_margin );
684
684
}
685
685
686
686
return ret ;
687
687
}
688
688
689
- static size_t callchain__fprintf_graph (FILE * fp , struct callchain_node * self ,
689
+ static size_t callchain__fprintf_graph (FILE * fp , struct rb_root * root ,
690
690
u64 total_samples , int left_margin )
691
691
{
692
+ struct callchain_node * cnode ;
692
693
struct callchain_list * chain ;
694
+ u32 entries_printed = 0 ;
693
695
bool printed = false;
696
+ struct rb_node * node ;
694
697
int i = 0 ;
695
- int ret = 0 ;
696
- u32 entries_printed = 0 ;
697
-
698
- list_for_each_entry (chain , & self -> val , list ) {
699
- if (!i ++ && sort__first_dimension == SORT_SYM )
700
- continue ;
701
-
702
- if (!printed ) {
703
- ret += callchain__fprintf_left_margin (fp , left_margin );
704
- ret += fprintf (fp , "|\n" );
705
- ret += callchain__fprintf_left_margin (fp , left_margin );
706
- ret += fprintf (fp , "---" );
707
-
708
- left_margin += 3 ;
709
- printed = true;
710
- } else
711
- ret += callchain__fprintf_left_margin (fp , left_margin );
698
+ int ret ;
712
699
713
- if (chain -> ms .sym )
714
- ret += fprintf (fp , " %s\n" , chain -> ms .sym -> name );
715
- else
716
- ret += fprintf (fp , " %p\n" , (void * )(long )chain -> ip );
700
+ /*
701
+ * If have one single callchain root, don't bother printing
702
+ * its percentage (100 % in fractal mode and the same percentage
703
+ * than the hist in graph mode). This also avoid one level of column.
704
+ */
705
+ node = rb_first (root );
706
+ if (node && !rb_next (node )) {
707
+ cnode = rb_entry (node , struct callchain_node , rb_node );
708
+ list_for_each_entry (chain , & cnode -> val , list ) {
709
+ /*
710
+ * If we sort by symbol, the first entry is the same than
711
+ * the symbol. No need to print it otherwise it appears as
712
+ * displayed twice.
713
+ */
714
+ if (!i ++ && sort__first_dimension == SORT_SYM )
715
+ continue ;
716
+ if (!printed ) {
717
+ ret += callchain__fprintf_left_margin (fp , left_margin );
718
+ ret += fprintf (fp , "|\n" );
719
+ ret += callchain__fprintf_left_margin (fp , left_margin );
720
+ ret += fprintf (fp , "---" );
721
+ left_margin += 3 ;
722
+ printed = true;
723
+ } else
724
+ ret += callchain__fprintf_left_margin (fp , left_margin );
725
+
726
+ if (chain -> ms .sym )
727
+ ret += fprintf (fp , " %s\n" , chain -> ms .sym -> name );
728
+ else
729
+ ret += fprintf (fp , " %p\n" , (void * )(long )chain -> ip );
717
730
718
- if (++ entries_printed == callchain_param .print_limit )
719
- break ;
731
+ if (++ entries_printed == callchain_param .print_limit )
732
+ break ;
733
+ }
734
+ root = & cnode -> rb_root ;
720
735
}
721
736
722
- ret += __callchain__fprintf_graph (fp , self , total_samples , 1 , 1 , left_margin );
723
-
724
- return ret ;
737
+ return __callchain__fprintf_graph (fp , root , total_samples ,
738
+ 1 , 1 , left_margin );
725
739
}
726
740
727
- static size_t callchain__fprintf_flat (FILE * fp , struct callchain_node * self ,
728
- u64 total_samples )
741
+ static size_t __callchain__fprintf_flat (FILE * fp ,
742
+ struct callchain_node * self ,
743
+ u64 total_samples )
729
744
{
730
745
struct callchain_list * chain ;
731
746
size_t ret = 0 ;
732
747
733
748
if (!self )
734
749
return 0 ;
735
750
736
- ret += callchain__fprintf_flat (fp , self -> parent , total_samples );
751
+ ret += __callchain__fprintf_flat (fp , self -> parent , total_samples );
737
752
738
753
739
754
list_for_each_entry (chain , & self -> val , list ) {
@@ -749,44 +764,58 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
749
764
return ret ;
750
765
}
751
766
752
- static size_t hist_entry_callchain__fprintf (struct hist_entry * he ,
753
- u64 total_samples , int left_margin ,
754
- FILE * fp )
767
+ static size_t callchain__fprintf_flat (FILE * fp , struct rb_root * self ,
768
+ u64 total_samples )
755
769
{
756
- struct rb_node * rb_node ;
757
- struct callchain_node * chain ;
758
770
size_t ret = 0 ;
759
771
u32 entries_printed = 0 ;
772
+ struct rb_node * rb_node ;
773
+ struct callchain_node * chain ;
760
774
761
- rb_node = rb_first (& he -> sorted_chain );
775
+ rb_node = rb_first (self );
762
776
while (rb_node ) {
763
777
double percent ;
764
778
765
779
chain = rb_entry (rb_node , struct callchain_node , rb_node );
766
780
percent = chain -> hit * 100.0 / total_samples ;
767
- switch (callchain_param .mode ) {
768
- case CHAIN_FLAT :
769
- ret += percent_color_fprintf (fp , " %6.2f%%\n" ,
770
- percent );
771
- ret += callchain__fprintf_flat (fp , chain , total_samples );
772
- break ;
773
- case CHAIN_GRAPH_ABS : /* Falldown */
774
- case CHAIN_GRAPH_REL :
775
- ret += callchain__fprintf_graph (fp , chain , total_samples ,
776
- left_margin );
777
- case CHAIN_NONE :
778
- default :
779
- break ;
780
- }
781
+
782
+ ret = percent_color_fprintf (fp , " %6.2f%%\n" , percent );
783
+ ret += __callchain__fprintf_flat (fp , chain , total_samples );
781
784
ret += fprintf (fp , "\n" );
782
785
if (++ entries_printed == callchain_param .print_limit )
783
786
break ;
787
+
784
788
rb_node = rb_next (rb_node );
785
789
}
786
790
787
791
return ret ;
788
792
}
789
793
794
+ static size_t hist_entry_callchain__fprintf (struct hist_entry * he ,
795
+ u64 total_samples , int left_margin ,
796
+ FILE * fp )
797
+ {
798
+ switch (callchain_param .mode ) {
799
+ case CHAIN_GRAPH_REL :
800
+ return callchain__fprintf_graph (fp , & he -> sorted_chain , he -> period ,
801
+ left_margin );
802
+ break ;
803
+ case CHAIN_GRAPH_ABS :
804
+ return callchain__fprintf_graph (fp , & he -> sorted_chain , total_samples ,
805
+ left_margin );
806
+ break ;
807
+ case CHAIN_FLAT :
808
+ return callchain__fprintf_flat (fp , & he -> sorted_chain , total_samples );
809
+ break ;
810
+ case CHAIN_NONE :
811
+ break ;
812
+ default :
813
+ pr_err ("Bad callchain mode\n" );
814
+ }
815
+
816
+ return 0 ;
817
+ }
818
+
790
819
void hists__output_recalc_col_len (struct hists * hists , int max_rows )
791
820
{
792
821
struct rb_node * next = rb_first (& hists -> entries );
0 commit comments