aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/ui/browsers/hists.c203
1 files changed, 80 insertions, 123 deletions
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 519353d9f5fb..d4cef68176da 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -477,20 +477,37 @@ static char *callchain_list__sym_name(struct callchain_list *cl,
477 return bf; 477 return bf;
478} 478}
479 479
480struct callchain_print_arg {
481 /* for hists browser */
482 off_t row_offset;
483 bool is_current_entry;
484
485 /* for file dump */
486 FILE *fp;
487 int printed;
488};
489
490typedef void (*print_callchain_entry_fn)(struct hist_browser *browser,
491 struct callchain_list *chain,
492 const char *str, int offset,
493 unsigned short row,
494 struct callchain_print_arg *arg);
495
480static void hist_browser__show_callchain_entry(struct hist_browser *browser, 496static void hist_browser__show_callchain_entry(struct hist_browser *browser,
481 struct callchain_list *chain, 497 struct callchain_list *chain,
482 unsigned short row, int offset, 498 const char *str, int offset,
483 char folded_sign, const char *str, 499 unsigned short row,
484 bool *is_current_entry) 500 struct callchain_print_arg *arg)
485{ 501{
486 int color, width; 502 int color, width;
503 char folded_sign = callchain_list__folded(chain);
487 504
488 color = HE_COLORSET_NORMAL; 505 color = HE_COLORSET_NORMAL;
489 width = browser->b.width - (offset + 2); 506 width = browser->b.width - (offset + 2);
490 if (ui_browser__is_current_entry(&browser->b, row)) { 507 if (ui_browser__is_current_entry(&browser->b, row)) {
491 browser->selection = &chain->ms; 508 browser->selection = &chain->ms;
492 color = HE_COLORSET_SELECTED; 509 color = HE_COLORSET_SELECTED;
493 *is_current_entry = true; 510 arg->is_current_entry = true;
494 } 511 }
495 512
496 ui_browser__set_color(&browser->b, color); 513 ui_browser__set_color(&browser->b, color);
@@ -500,12 +517,41 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
500 slsmg_write_nstring(str, width); 517 slsmg_write_nstring(str, width);
501} 518}
502 519
520static void hist_browser__fprintf_callchain_entry(struct hist_browser *b __maybe_unused,
521 struct callchain_list *chain,
522 const char *str, int offset,
523 unsigned short row __maybe_unused,
524 struct callchain_print_arg *arg)
525{
526 char folded_sign = callchain_list__folded(chain);
527
528 arg->printed += fprintf(arg->fp, "%*s%c %s\n", offset, " ",
529 folded_sign, str);
530}
531
532typedef bool (*check_output_full_fn)(struct hist_browser *browser,
533 unsigned short row);
534
535static bool hist_browser__check_output_full(struct hist_browser *browser,
536 unsigned short row)
537{
538 return browser->b.rows == row;
539}
540
541static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_unused,
542 unsigned short row __maybe_unused)
543{
544 return false;
545}
546
503#define LEVEL_OFFSET_STEP 3 547#define LEVEL_OFFSET_STEP 3
504 548
505static int hist_browser__show_callchain(struct hist_browser *browser, 549static int hist_browser__show_callchain(struct hist_browser *browser,
506 struct rb_root *root, int level, 550 struct rb_root *root, int level,
507 unsigned short row, off_t *row_offset, 551 unsigned short row, u64 total,
508 u64 total, bool *is_current_entry) 552 print_callchain_entry_fn print,
553 struct callchain_print_arg *arg,
554 check_output_full_fn is_output_full)
509{ 555{
510 struct rb_node *node; 556 struct rb_node *node;
511 int first_row = row, offset = level * LEVEL_OFFSET_STEP; 557 int first_row = row, offset = level * LEVEL_OFFSET_STEP;
@@ -532,8 +578,8 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
532 extra_offset = LEVEL_OFFSET_STEP; 578 extra_offset = LEVEL_OFFSET_STEP;
533 579
534 folded_sign = callchain_list__folded(chain); 580 folded_sign = callchain_list__folded(chain);
535 if (*row_offset != 0) { 581 if (arg->row_offset != 0) {
536 --*row_offset; 582 arg->row_offset--;
537 goto do_next; 583 goto do_next;
538 } 584 }
539 585
@@ -550,13 +596,11 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
550 str = alloc_str; 596 str = alloc_str;
551 } 597 }
552 598
553 hist_browser__show_callchain_entry(browser, chain, row, 599 print(browser, chain, str, offset + extra_offset, row, arg);
554 offset + extra_offset, 600
555 folded_sign, str,
556 is_current_entry);
557 free(alloc_str); 601 free(alloc_str);
558 602
559 if (++row == browser->b.rows) 603 if (is_output_full(browser, ++row))
560 goto out; 604 goto out;
561do_next: 605do_next:
562 if (folded_sign == '+') 606 if (folded_sign == '+')
@@ -572,12 +616,10 @@ do_next:
572 new_total = total; 616 new_total = total;
573 617
574 row += hist_browser__show_callchain(browser, &child->rb_root, 618 row += hist_browser__show_callchain(browser, &child->rb_root,
575 new_level, 619 new_level, row, new_total,
576 row, row_offset, 620 print, arg, is_output_full);
577 new_total,
578 is_current_entry);
579 } 621 }
580 if (row == browser->b.rows) 622 if (is_output_full(browser, row))
581 break; 623 break;
582 node = next; 624 node = next;
583 } 625 }
@@ -757,16 +799,20 @@ static int hist_browser__show_entry(struct hist_browser *browser,
757 799
758 if (folded_sign == '-' && row != browser->b.rows) { 800 if (folded_sign == '-' && row != browser->b.rows) {
759 u64 total = hists__total_period(entry->hists); 801 u64 total = hists__total_period(entry->hists);
802 struct callchain_print_arg arg = {
803 .row_offset = row_offset,
804 .is_current_entry = current_entry,
805 };
760 806
761 if (symbol_conf.cumulate_callchain) 807 if (symbol_conf.cumulate_callchain)
762 total = entry->stat_acc->period; 808 total = entry->stat_acc->period;
763 809
764 printed += hist_browser__show_callchain(browser, 810 printed += hist_browser__show_callchain(browser,
765 &entry->sorted_chain, 811 &entry->sorted_chain, 1, row, total,
766 1, row, &row_offset, 812 hist_browser__show_callchain_entry, &arg,
767 total, &current_entry); 813 hist_browser__check_output_full);
768 814
769 if (current_entry) 815 if (arg.is_current_entry)
770 browser->he_selection = entry; 816 browser->he_selection = entry;
771 } 817 }
772 818
@@ -1022,110 +1068,21 @@ do_offset:
1022 } 1068 }
1023} 1069}
1024 1070
1025static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
1026 struct callchain_node *chain_node,
1027 u64 total, int level,
1028 FILE *fp)
1029{
1030 struct rb_node *node;
1031 int offset = level * LEVEL_OFFSET_STEP;
1032 u64 new_total;
1033 int printed = 0;
1034
1035 if (callchain_param.mode == CHAIN_GRAPH_REL)
1036 new_total = chain_node->children_hit;
1037 else
1038 new_total = total;
1039
1040 node = rb_first(&chain_node->rb_root);
1041 while (node) {
1042 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
1043 struct rb_node *next = rb_next(node);
1044 u64 cumul = callchain_cumul_hits(child);
1045 struct callchain_list *chain;
1046 char folded_sign = ' ';
1047 int first = true;
1048 int extra_offset = 0;
1049
1050 list_for_each_entry(chain, &child->val, list) {
1051 char bf[1024], *alloc_str;
1052 const char *str;
1053 bool was_first = first;
1054
1055 if (first)
1056 first = false;
1057 else
1058 extra_offset = LEVEL_OFFSET_STEP;
1059
1060 folded_sign = callchain_list__folded(chain);
1061
1062 alloc_str = NULL;
1063 str = callchain_list__sym_name(chain, bf, sizeof(bf),
1064 browser->show_dso);
1065 if (was_first) {
1066 double percent = cumul * 100.0 / new_total;
1067
1068 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
1069 str = "Not enough memory!";
1070 else
1071 str = alloc_str;
1072 }
1073
1074 printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
1075 free(alloc_str);
1076 if (folded_sign == '+')
1077 break;
1078 }
1079
1080 if (folded_sign == '-') {
1081 const int new_level = level + (extra_offset ? 2 : 1);
1082 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
1083 new_level, fp);
1084 }
1085
1086 node = next;
1087 }
1088
1089 return printed;
1090}
1091
1092static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
1093 struct callchain_node *node,
1094 int level, FILE *fp)
1095{
1096 struct callchain_list *chain;
1097 int offset = level * LEVEL_OFFSET_STEP;
1098 char folded_sign = ' ';
1099 int printed = 0;
1100
1101 list_for_each_entry(chain, &node->val, list) {
1102 char bf[1024], *s;
1103
1104 folded_sign = callchain_list__folded(chain);
1105 s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso);
1106 printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
1107 }
1108
1109 if (folded_sign == '-')
1110 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
1111 browser->hists->stats.total_period,
1112 level + 1, fp);
1113 return printed;
1114}
1115
1116static int hist_browser__fprintf_callchain(struct hist_browser *browser, 1071static int hist_browser__fprintf_callchain(struct hist_browser *browser,
1117 struct rb_root *chain, int level, FILE *fp) 1072 struct hist_entry *he, FILE *fp)
1118{ 1073{
1119 struct rb_node *nd; 1074 u64 total = hists__total_period(he->hists);
1120 int printed = 0; 1075 struct callchain_print_arg arg = {
1121 1076 .fp = fp,
1122 for (nd = rb_first(chain); nd; nd = rb_next(nd)) { 1077 };
1123 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
1124 1078
1125 printed += hist_browser__fprintf_callchain_node(browser, node, level, fp); 1079 if (symbol_conf.cumulate_callchain)
1126 } 1080 total = he->stat_acc->period;
1127 1081
1128 return printed; 1082 hist_browser__show_callchain(browser, &he->sorted_chain, 1, 0, total,
1083 hist_browser__fprintf_callchain_entry, &arg,
1084 hist_browser__check_dump_full);
1085 return arg.printed;
1129} 1086}
1130 1087
1131static int hist_browser__fprintf_entry(struct hist_browser *browser, 1088static int hist_browser__fprintf_entry(struct hist_browser *browser,
@@ -1164,7 +1121,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1164 printed += fprintf(fp, "%s\n", rtrim(s)); 1121 printed += fprintf(fp, "%s\n", rtrim(s));
1165 1122
1166 if (folded_sign == '-') 1123 if (folded_sign == '-')
1167 printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp); 1124 printed += hist_browser__fprintf_callchain(browser, he, fp);
1168 1125
1169 return printed; 1126 return printed;
1170} 1127}