aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/ui/browsers
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2014-08-21 20:13:21 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-08-24 07:11:19 -0400
commit39ee533fcc7feb5b7938a3973a2bf5ad79bb595b (patch)
treedd8436b2fdeacf12dec49cde06f9a9b50bf7c11a /tools/perf/ui/browsers
parent2f3f9bcf000b2043a480e7cc0cae582559fb0f13 (diff)
perf hists browser: Consolidate callchain print functions in TUI
Currently there're two callchain print functions in TUI - one for the hists browser and another for file dump. They do almost same job so it'd be better consolidate the codes. To do that, provide two callbacks to the generic logic - one for printing and another for checking whether it should stop. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Andi Kleen <andi@firstfloor.org> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung.kim@lge.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1408666401-594-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/ui/browsers')
-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}