aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2016-03-07 14:44:46 -0500
committerIngo Molnar <mingo@kernel.org>2016-03-08 04:11:19 -0500
commit1b2dbbf41a0f4cf7a5662bccb9a18128d16e5ffb (patch)
tree284079169d6939125553b2946ebd2318019029d8
parentc3bc0c436899d01c3a09fddb308d487cc032fbd2 (diff)
perf hists: Use own hpp_list for hierarchy mode
Now each hists has its own hpp lists in hierarchy. So instead of having a pointer to a single perf_hpp_fmt in a hist entry, make it point the hpp_list for its level. This will be used to support multiple sort keys in a single hierarchy level. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/r/1457361308-514-3-git-send-email-namhyung@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/ui/browsers/hists.c45
-rw-r--r--tools/perf/ui/gtk/hists.c20
-rw-r--r--tools/perf/ui/hist.c5
-rw-r--r--tools/perf/ui/stdio/hist.c44
-rw-r--r--tools/perf/util/hist.c60
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/sort.h1
7 files changed, 103 insertions, 73 deletions
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 5ffffcb1e3c5..928b4825b752 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1388,25 +1388,26 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
1388 HE_COLORSET_NORMAL); 1388 HE_COLORSET_NORMAL);
1389 } 1389 }
1390 1390
1391 ui_browser__write_nstring(&browser->b, "", 2); 1391 perf_hpp_list__for_each_format(entry->hpp_list, fmt) {
1392 width -= 2; 1392 ui_browser__write_nstring(&browser->b, "", 2);
1393 width -= 2;
1393 1394
1394 /* 1395 /*
1395 * No need to call hist_entry__snprintf_alignment() 1396 * No need to call hist_entry__snprintf_alignment()
1396 * since this fmt is always the last column in the 1397 * since this fmt is always the last column in the
1397 * hierarchy mode. 1398 * hierarchy mode.
1398 */ 1399 */
1399 fmt = entry->fmt; 1400 if (fmt->color) {
1400 if (fmt->color) { 1401 width -= fmt->color(fmt, &hpp, entry);
1401 width -= fmt->color(fmt, &hpp, entry); 1402 } else {
1402 } else { 1403 int i = 0;
1403 int i = 0;
1404 1404
1405 width -= fmt->entry(fmt, &hpp, entry); 1405 width -= fmt->entry(fmt, &hpp, entry);
1406 ui_browser__printf(&browser->b, "%s", ltrim(s)); 1406 ui_browser__printf(&browser->b, "%s", ltrim(s));
1407 1407
1408 while (isspace(s[i++])) 1408 while (isspace(s[i++]))
1409 width++; 1409 width++;
1410 }
1410 } 1411 }
1411 } 1412 }
1412 1413
@@ -1934,7 +1935,7 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
1934 struct perf_hpp_fmt *fmt; 1935 struct perf_hpp_fmt *fmt;
1935 bool first = true; 1936 bool first = true;
1936 int ret; 1937 int ret;
1937 int hierarchy_indent = (nr_sort_keys + 1) * HIERARCHY_INDENT; 1938 int hierarchy_indent = nr_sort_keys * HIERARCHY_INDENT;
1938 1939
1939 printed = fprintf(fp, "%*s", level * HIERARCHY_INDENT, ""); 1940 printed = fprintf(fp, "%*s", level * HIERARCHY_INDENT, "");
1940 1941
@@ -1962,9 +1963,13 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
1962 ret = scnprintf(hpp.buf, hpp.size, "%*s", hierarchy_indent, ""); 1963 ret = scnprintf(hpp.buf, hpp.size, "%*s", hierarchy_indent, "");
1963 advance_hpp(&hpp, ret); 1964 advance_hpp(&hpp, ret);
1964 1965
1965 fmt = he->fmt; 1966 perf_hpp_list__for_each_format(he->hpp_list, fmt) {
1966 ret = fmt->entry(fmt, &hpp, he); 1967 ret = scnprintf(hpp.buf, hpp.size, " ");
1967 advance_hpp(&hpp, ret); 1968 advance_hpp(&hpp, ret);
1969
1970 ret = fmt->entry(fmt, &hpp, he);
1971 advance_hpp(&hpp, ret);
1972 }
1968 1973
1969 printed += fprintf(fp, "%s\n", rtrim(s)); 1974 printed += fprintf(fp, "%s\n", rtrim(s));
1970 1975
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index a5758fdfbe1f..4534e2d7669c 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -412,6 +412,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
412 for (node = rb_first(root); node; node = rb_next(node)) { 412 for (node = rb_first(root); node; node = rb_next(node)) {
413 GtkTreeIter iter; 413 GtkTreeIter iter;
414 float percent; 414 float percent;
415 char *bf;
415 416
416 he = rb_entry(node, struct hist_entry, rb_node); 417 he = rb_entry(node, struct hist_entry, rb_node);
417 if (he->filtered) 418 if (he->filtered)
@@ -437,13 +438,20 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
437 gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1); 438 gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
438 } 439 }
439 440
440 fmt = he->fmt; 441 bf = hpp->buf;
441 if (fmt->color) 442 perf_hpp_list__for_each_format(he->hpp_list, fmt) {
442 fmt->color(fmt, hpp, he); 443 int ret;
443 else 444
444 fmt->entry(fmt, hpp, he); 445 if (fmt->color)
446 ret = fmt->color(fmt, hpp, he);
447 else
448 ret = fmt->entry(fmt, hpp, he);
449
450 snprintf(hpp->buf + ret, hpp->size - ret, " ");
451 advance_hpp(hpp, ret + 2);
452 }
445 453
446 gtk_tree_store_set(store, &iter, col_idx, rtrim(hpp->buf), -1); 454 gtk_tree_store_set(store, &iter, col_idx, rtrim(bf), -1);
447 455
448 if (!he->leaf) { 456 if (!he->leaf) {
449 perf_gtk__add_hierarchy_entries(hists, &he->hroot_out, 457 perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 3a15e844f89a..95795ef4209b 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -722,6 +722,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
722 struct perf_hpp_list_node *node = NULL; 722 struct perf_hpp_list_node *node = NULL;
723 struct perf_hpp_fmt *fmt_copy; 723 struct perf_hpp_fmt *fmt_copy;
724 bool found = false; 724 bool found = false;
725 bool skip = perf_hpp__should_skip(fmt, hists);
725 726
726 list_for_each_entry(node, &hists->hpp_formats, list) { 727 list_for_each_entry(node, &hists->hpp_formats, list) {
727 if (node->level == fmt->level) { 728 if (node->level == fmt->level) {
@@ -735,6 +736,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
735 if (node == NULL) 736 if (node == NULL)
736 return -1; 737 return -1;
737 738
739 node->skip = skip;
738 node->level = fmt->level; 740 node->level = fmt->level;
739 perf_hpp_list__init(&node->hpp); 741 perf_hpp_list__init(&node->hpp);
740 742
@@ -745,6 +747,9 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
745 if (fmt_copy == NULL) 747 if (fmt_copy == NULL)
746 return -1; 748 return -1;
747 749
750 if (!skip)
751 node->skip = false;
752
748 list_add_tail(&fmt_copy->list, &node->hpp.fields); 753 list_add_tail(&fmt_copy->list, &node->hpp.fields);
749 list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts); 754 list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts);
750 755
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 6d06fbb365b6..073642a63cc9 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -451,33 +451,33 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
451 advance_hpp(hpp, ret); 451 advance_hpp(hpp, ret);
452 } 452 }
453 453
454 if (sep) 454 if (!sep)
455 ret = scnprintf(hpp->buf, hpp->size, "%s", sep);
456 else
457 ret = scnprintf(hpp->buf, hpp->size, "%*s", 455 ret = scnprintf(hpp->buf, hpp->size, "%*s",
458 (nr_sort_key - 1) * HIERARCHY_INDENT + 2, ""); 456 (nr_sort_key - 1) * HIERARCHY_INDENT, "");
459 advance_hpp(hpp, ret); 457 advance_hpp(hpp, ret);
460 458
461 printed += fprintf(fp, "%s", buf); 459 printed += fprintf(fp, "%s", buf);
462 460
463 hpp->buf = buf; 461 perf_hpp_list__for_each_format(he->hpp_list, fmt) {
464 hpp->size = size; 462 hpp->buf = buf;
465 463 hpp->size = size;
466 /* 464
467 * No need to call hist_entry__snprintf_alignment() since this 465 /*
468 * fmt is always the last column in the hierarchy mode. 466 * No need to call hist_entry__snprintf_alignment() since this
469 */ 467 * fmt is always the last column in the hierarchy mode.
470 fmt = he->fmt; 468 */
471 if (perf_hpp__use_color() && fmt->color) 469 if (perf_hpp__use_color() && fmt->color)
472 fmt->color(fmt, hpp, he); 470 fmt->color(fmt, hpp, he);
473 else 471 else
474 fmt->entry(fmt, hpp, he); 472 fmt->entry(fmt, hpp, he);
475 473
476 /* 474 /*
477 * dynamic entries are right-aligned but we want left-aligned 475 * dynamic entries are right-aligned but we want left-aligned
478 * in the hierarchy mode 476 * in the hierarchy mode
479 */ 477 */
480 printed += fprintf(fp, "%s\n", ltrim(buf)); 478 printed += fprintf(fp, "%s%s", sep ?: " ", ltrim(buf));
479 }
480 printed += putc('\n', fp);
481 481
482 if (symbol_conf.use_callchain && he->leaf) { 482 if (symbol_conf.use_callchain && he->leaf) {
483 u64 total = hists__total_period(hists); 483 u64 total = hists__total_period(hists);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index fea92fcb6903..29da9e0d8db9 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1091,18 +1091,25 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he);
1091static struct hist_entry *hierarchy_insert_entry(struct hists *hists, 1091static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
1092 struct rb_root *root, 1092 struct rb_root *root,
1093 struct hist_entry *he, 1093 struct hist_entry *he,
1094 struct perf_hpp_fmt *fmt) 1094 struct perf_hpp_list *hpp_list)
1095{ 1095{
1096 struct rb_node **p = &root->rb_node; 1096 struct rb_node **p = &root->rb_node;
1097 struct rb_node *parent = NULL; 1097 struct rb_node *parent = NULL;
1098 struct hist_entry *iter, *new; 1098 struct hist_entry *iter, *new;
1099 struct perf_hpp_fmt *fmt;
1099 int64_t cmp; 1100 int64_t cmp;
1100 1101
1101 while (*p != NULL) { 1102 while (*p != NULL) {
1102 parent = *p; 1103 parent = *p;
1103 iter = rb_entry(parent, struct hist_entry, rb_node_in); 1104 iter = rb_entry(parent, struct hist_entry, rb_node_in);
1104 1105
1105 cmp = fmt->collapse(fmt, iter, he); 1106 cmp = 0;
1107 perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
1108 cmp = fmt->collapse(fmt, iter, he);
1109 if (cmp)
1110 break;
1111 }
1112
1106 if (!cmp) { 1113 if (!cmp) {
1107 he_stat__add_stat(&iter->stat, &he->stat); 1114 he_stat__add_stat(&iter->stat, &he->stat);
1108 return iter; 1115 return iter;
@@ -1121,24 +1128,26 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
1121 hists__apply_filters(hists, new); 1128 hists__apply_filters(hists, new);
1122 hists->nr_entries++; 1129 hists->nr_entries++;
1123 1130
1124 /* save related format for output */ 1131 /* save related format list for output */
1125 new->fmt = fmt; 1132 new->hpp_list = hpp_list;
1126 1133
1127 /* some fields are now passed to 'new' */ 1134 /* some fields are now passed to 'new' */
1128 if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt)) 1135 perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
1129 he->trace_output = NULL; 1136 if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
1130 else 1137 he->trace_output = NULL;
1131 new->trace_output = NULL; 1138 else
1139 new->trace_output = NULL;
1132 1140
1133 if (perf_hpp__is_srcline_entry(fmt)) 1141 if (perf_hpp__is_srcline_entry(fmt))
1134 he->srcline = NULL; 1142 he->srcline = NULL;
1135 else 1143 else
1136 new->srcline = NULL; 1144 new->srcline = NULL;
1137 1145
1138 if (perf_hpp__is_srcfile_entry(fmt)) 1146 if (perf_hpp__is_srcfile_entry(fmt))
1139 he->srcfile = NULL; 1147 he->srcfile = NULL;
1140 else 1148 else
1141 new->srcfile = NULL; 1149 new->srcfile = NULL;
1150 }
1142 1151
1143 rb_link_node(&new->rb_node_in, parent, p); 1152 rb_link_node(&new->rb_node_in, parent, p);
1144 rb_insert_color(&new->rb_node_in, root); 1153 rb_insert_color(&new->rb_node_in, root);
@@ -1149,21 +1158,19 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
1149 struct rb_root *root, 1158 struct rb_root *root,
1150 struct hist_entry *he) 1159 struct hist_entry *he)
1151{ 1160{
1152 struct perf_hpp_fmt *fmt; 1161 struct perf_hpp_list_node *node;
1153 struct hist_entry *new_he = NULL; 1162 struct hist_entry *new_he = NULL;
1154 struct hist_entry *parent = NULL; 1163 struct hist_entry *parent = NULL;
1155 int depth = 0; 1164 int depth = 0;
1156 int ret = 0; 1165 int ret = 0;
1157 1166
1158 hists__for_each_sort_list(hists, fmt) { 1167 list_for_each_entry(node, &hists->hpp_formats, list) {
1159 if (!perf_hpp__is_sort_entry(fmt) && 1168 /* skip period (overhead) and elided columns */
1160 !perf_hpp__is_dynamic_entry(fmt)) 1169 if (node->level == 0 || node->skip)
1161 continue;
1162 if (perf_hpp__should_skip(fmt, hists))
1163 continue; 1170 continue;
1164 1171
1165 /* insert copy of 'he' for each fmt into the hierarchy */ 1172 /* insert copy of 'he' for each fmt into the hierarchy */
1166 new_he = hierarchy_insert_entry(hists, root, he, fmt); 1173 new_he = hierarchy_insert_entry(hists, root, he, &node->hpp);
1167 if (new_he == NULL) { 1174 if (new_he == NULL) {
1168 ret = -1; 1175 ret = -1;
1169 break; 1176 break;
@@ -1358,6 +1365,7 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
1358 struct rb_node **p = &root->rb_node; 1365 struct rb_node **p = &root->rb_node;
1359 struct rb_node *parent = NULL; 1366 struct rb_node *parent = NULL;
1360 struct hist_entry *iter; 1367 struct hist_entry *iter;
1368 struct perf_hpp_fmt *fmt;
1361 1369
1362 while (*p != NULL) { 1370 while (*p != NULL) {
1363 parent = *p; 1371 parent = *p;
@@ -1373,8 +1381,10 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
1373 rb_insert_color(&he->rb_node, root); 1381 rb_insert_color(&he->rb_node, root);
1374 1382
1375 /* update column width of dynamic entry */ 1383 /* update column width of dynamic entry */
1376 if (perf_hpp__is_dynamic_entry(he->fmt)) 1384 perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
1377 he->fmt->sort(he->fmt, he, NULL); 1385 if (perf_hpp__is_dynamic_entry(fmt))
1386 fmt->sort(fmt, he, NULL);
1387 }
1378} 1388}
1379 1389
1380static void hists__hierarchy_output_resort(struct hists *hists, 1390static void hists__hierarchy_output_resort(struct hists *hists,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 3cab9dc20822..2209188d729c 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -249,6 +249,7 @@ struct perf_hpp_list_node {
249 struct list_head list; 249 struct list_head list;
250 struct perf_hpp_list hpp; 250 struct perf_hpp_list hpp;
251 int level; 251 int level;
252 bool skip;
252}; 253};
253 254
254void perf_hpp_list__column_register(struct perf_hpp_list *list, 255void perf_hpp_list__column_register(struct perf_hpp_list *list,
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 25a5529a94e4..ea1f722cffea 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -130,6 +130,7 @@ struct hist_entry {
130 u32 raw_size; 130 u32 raw_size;
131 void *trace_output; 131 void *trace_output;
132 struct perf_hpp_fmt *fmt; 132 struct perf_hpp_fmt *fmt;
133 struct perf_hpp_list *hpp_list;
133 struct hist_entry *parent_he; 134 struct hist_entry *parent_he;
134 union { 135 union {
135 /* this is for hierarchical entry structure */ 136 /* this is for hierarchical entry structure */