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>
This commit is contained in:
Namhyung Kim 2016-03-07 16:44:46 -03:00 committed by Ingo Molnar
parent c3bc0c4368
commit 1b2dbbf41a
7 changed files with 101 additions and 71 deletions

View File

@ -1388,25 +1388,26 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
HE_COLORSET_NORMAL); HE_COLORSET_NORMAL);
} }
ui_browser__write_nstring(&browser->b, "", 2); perf_hpp_list__for_each_format(entry->hpp_list, fmt) {
width -= 2; ui_browser__write_nstring(&browser->b, "", 2);
width -= 2;
/* /*
* No need to call hist_entry__snprintf_alignment() * No need to call hist_entry__snprintf_alignment()
* since this fmt is always the last column in the * since this fmt is always the last column in the
* hierarchy mode. * hierarchy mode.
*/ */
fmt = entry->fmt; if (fmt->color) {
if (fmt->color) { width -= fmt->color(fmt, &hpp, entry);
width -= fmt->color(fmt, &hpp, entry); } else {
} else { int i = 0;
int i = 0;
width -= fmt->entry(fmt, &hpp, entry); width -= fmt->entry(fmt, &hpp, entry);
ui_browser__printf(&browser->b, "%s", ltrim(s)); ui_browser__printf(&browser->b, "%s", ltrim(s));
while (isspace(s[i++])) while (isspace(s[i++]))
width++; width++;
}
} }
} }
@ -1934,7 +1935,7 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
struct perf_hpp_fmt *fmt; struct perf_hpp_fmt *fmt;
bool first = true; bool first = true;
int ret; int ret;
int hierarchy_indent = (nr_sort_keys + 1) * HIERARCHY_INDENT; int hierarchy_indent = nr_sort_keys * HIERARCHY_INDENT;
printed = fprintf(fp, "%*s", level * HIERARCHY_INDENT, ""); printed = fprintf(fp, "%*s", level * HIERARCHY_INDENT, "");
@ -1962,9 +1963,13 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
ret = scnprintf(hpp.buf, hpp.size, "%*s", hierarchy_indent, ""); ret = scnprintf(hpp.buf, hpp.size, "%*s", hierarchy_indent, "");
advance_hpp(&hpp, ret); advance_hpp(&hpp, ret);
fmt = he->fmt; perf_hpp_list__for_each_format(he->hpp_list, fmt) {
ret = fmt->entry(fmt, &hpp, he); ret = scnprintf(hpp.buf, hpp.size, " ");
advance_hpp(&hpp, ret); advance_hpp(&hpp, ret);
ret = fmt->entry(fmt, &hpp, he);
advance_hpp(&hpp, ret);
}
printed += fprintf(fp, "%s\n", rtrim(s)); printed += fprintf(fp, "%s\n", rtrim(s));

View File

@ -412,6 +412,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
for (node = rb_first(root); node; node = rb_next(node)) { for (node = rb_first(root); node; node = rb_next(node)) {
GtkTreeIter iter; GtkTreeIter iter;
float percent; float percent;
char *bf;
he = rb_entry(node, struct hist_entry, rb_node); he = rb_entry(node, struct hist_entry, rb_node);
if (he->filtered) if (he->filtered)
@ -437,13 +438,20 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1); gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
} }
fmt = he->fmt; bf = hpp->buf;
if (fmt->color) perf_hpp_list__for_each_format(he->hpp_list, fmt) {
fmt->color(fmt, hpp, he); int ret;
else
fmt->entry(fmt, hpp, he);
gtk_tree_store_set(store, &iter, col_idx, rtrim(hpp->buf), -1); if (fmt->color)
ret = fmt->color(fmt, hpp, he);
else
ret = fmt->entry(fmt, hpp, he);
snprintf(hpp->buf + ret, hpp->size - ret, " ");
advance_hpp(hpp, ret + 2);
}
gtk_tree_store_set(store, &iter, col_idx, rtrim(bf), -1);
if (!he->leaf) { if (!he->leaf) {
perf_gtk__add_hierarchy_entries(hists, &he->hroot_out, perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,

View File

@ -722,6 +722,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
struct perf_hpp_list_node *node = NULL; struct perf_hpp_list_node *node = NULL;
struct perf_hpp_fmt *fmt_copy; struct perf_hpp_fmt *fmt_copy;
bool found = false; bool found = false;
bool skip = perf_hpp__should_skip(fmt, hists);
list_for_each_entry(node, &hists->hpp_formats, list) { list_for_each_entry(node, &hists->hpp_formats, list) {
if (node->level == fmt->level) { if (node->level == fmt->level) {
@ -735,6 +736,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
if (node == NULL) if (node == NULL)
return -1; return -1;
node->skip = skip;
node->level = fmt->level; node->level = fmt->level;
perf_hpp_list__init(&node->hpp); perf_hpp_list__init(&node->hpp);
@ -745,6 +747,9 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
if (fmt_copy == NULL) if (fmt_copy == NULL)
return -1; return -1;
if (!skip)
node->skip = false;
list_add_tail(&fmt_copy->list, &node->hpp.fields); list_add_tail(&fmt_copy->list, &node->hpp.fields);
list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts); list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts);

View File

@ -451,33 +451,33 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
advance_hpp(hpp, ret); advance_hpp(hpp, ret);
} }
if (sep) if (!sep)
ret = scnprintf(hpp->buf, hpp->size, "%s", sep);
else
ret = scnprintf(hpp->buf, hpp->size, "%*s", ret = scnprintf(hpp->buf, hpp->size, "%*s",
(nr_sort_key - 1) * HIERARCHY_INDENT + 2, ""); (nr_sort_key - 1) * HIERARCHY_INDENT, "");
advance_hpp(hpp, ret); advance_hpp(hpp, ret);
printed += fprintf(fp, "%s", buf); printed += fprintf(fp, "%s", buf);
hpp->buf = buf; perf_hpp_list__for_each_format(he->hpp_list, fmt) {
hpp->size = size; hpp->buf = buf;
hpp->size = size;
/* /*
* No need to call hist_entry__snprintf_alignment() since this * No need to call hist_entry__snprintf_alignment() since this
* fmt is always the last column in the hierarchy mode. * fmt is always the last column in the hierarchy mode.
*/ */
fmt = he->fmt; if (perf_hpp__use_color() && fmt->color)
if (perf_hpp__use_color() && fmt->color) fmt->color(fmt, hpp, he);
fmt->color(fmt, hpp, he); else
else fmt->entry(fmt, hpp, he);
fmt->entry(fmt, hpp, he);
/* /*
* dynamic entries are right-aligned but we want left-aligned * dynamic entries are right-aligned but we want left-aligned
* in the hierarchy mode * in the hierarchy mode
*/ */
printed += fprintf(fp, "%s\n", ltrim(buf)); printed += fprintf(fp, "%s%s", sep ?: " ", ltrim(buf));
}
printed += putc('\n', fp);
if (symbol_conf.use_callchain && he->leaf) { if (symbol_conf.use_callchain && he->leaf) {
u64 total = hists__total_period(hists); u64 total = hists__total_period(hists);

View File

@ -1091,18 +1091,25 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he);
static struct hist_entry *hierarchy_insert_entry(struct hists *hists, static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
struct rb_root *root, struct rb_root *root,
struct hist_entry *he, struct hist_entry *he,
struct perf_hpp_fmt *fmt) struct perf_hpp_list *hpp_list)
{ {
struct rb_node **p = &root->rb_node; struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL; struct rb_node *parent = NULL;
struct hist_entry *iter, *new; struct hist_entry *iter, *new;
struct perf_hpp_fmt *fmt;
int64_t cmp; int64_t cmp;
while (*p != NULL) { while (*p != NULL) {
parent = *p; parent = *p;
iter = rb_entry(parent, struct hist_entry, rb_node_in); iter = rb_entry(parent, struct hist_entry, rb_node_in);
cmp = fmt->collapse(fmt, iter, he); cmp = 0;
perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
cmp = fmt->collapse(fmt, iter, he);
if (cmp)
break;
}
if (!cmp) { if (!cmp) {
he_stat__add_stat(&iter->stat, &he->stat); he_stat__add_stat(&iter->stat, &he->stat);
return iter; return iter;
@ -1121,24 +1128,26 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
hists__apply_filters(hists, new); hists__apply_filters(hists, new);
hists->nr_entries++; hists->nr_entries++;
/* save related format for output */ /* save related format list for output */
new->fmt = fmt; new->hpp_list = hpp_list;
/* some fields are now passed to 'new' */ /* some fields are now passed to 'new' */
if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt)) perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
he->trace_output = NULL; if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
else he->trace_output = NULL;
new->trace_output = NULL; else
new->trace_output = NULL;
if (perf_hpp__is_srcline_entry(fmt)) if (perf_hpp__is_srcline_entry(fmt))
he->srcline = NULL; he->srcline = NULL;
else else
new->srcline = NULL; new->srcline = NULL;
if (perf_hpp__is_srcfile_entry(fmt)) if (perf_hpp__is_srcfile_entry(fmt))
he->srcfile = NULL; he->srcfile = NULL;
else else
new->srcfile = NULL; new->srcfile = NULL;
}
rb_link_node(&new->rb_node_in, parent, p); rb_link_node(&new->rb_node_in, parent, p);
rb_insert_color(&new->rb_node_in, root); rb_insert_color(&new->rb_node_in, root);
@ -1149,21 +1158,19 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
struct rb_root *root, struct rb_root *root,
struct hist_entry *he) struct hist_entry *he)
{ {
struct perf_hpp_fmt *fmt; struct perf_hpp_list_node *node;
struct hist_entry *new_he = NULL; struct hist_entry *new_he = NULL;
struct hist_entry *parent = NULL; struct hist_entry *parent = NULL;
int depth = 0; int depth = 0;
int ret = 0; int ret = 0;
hists__for_each_sort_list(hists, fmt) { list_for_each_entry(node, &hists->hpp_formats, list) {
if (!perf_hpp__is_sort_entry(fmt) && /* skip period (overhead) and elided columns */
!perf_hpp__is_dynamic_entry(fmt)) if (node->level == 0 || node->skip)
continue;
if (perf_hpp__should_skip(fmt, hists))
continue; continue;
/* insert copy of 'he' for each fmt into the hierarchy */ /* insert copy of 'he' for each fmt into the hierarchy */
new_he = hierarchy_insert_entry(hists, root, he, fmt); new_he = hierarchy_insert_entry(hists, root, he, &node->hpp);
if (new_he == NULL) { if (new_he == NULL) {
ret = -1; ret = -1;
break; break;
@ -1358,6 +1365,7 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
struct rb_node **p = &root->rb_node; struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL; struct rb_node *parent = NULL;
struct hist_entry *iter; struct hist_entry *iter;
struct perf_hpp_fmt *fmt;
while (*p != NULL) { while (*p != NULL) {
parent = *p; parent = *p;
@ -1373,8 +1381,10 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
rb_insert_color(&he->rb_node, root); rb_insert_color(&he->rb_node, root);
/* update column width of dynamic entry */ /* update column width of dynamic entry */
if (perf_hpp__is_dynamic_entry(he->fmt)) perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
he->fmt->sort(he->fmt, he, NULL); if (perf_hpp__is_dynamic_entry(fmt))
fmt->sort(fmt, he, NULL);
}
} }
static void hists__hierarchy_output_resort(struct hists *hists, static void hists__hierarchy_output_resort(struct hists *hists,

View File

@ -249,6 +249,7 @@ struct perf_hpp_list_node {
struct list_head list; struct list_head list;
struct perf_hpp_list hpp; struct perf_hpp_list hpp;
int level; int level;
bool skip;
}; };
void perf_hpp_list__column_register(struct perf_hpp_list *list, void perf_hpp_list__column_register(struct perf_hpp_list *list,

View File

@ -130,6 +130,7 @@ struct hist_entry {
u32 raw_size; u32 raw_size;
void *trace_output; void *trace_output;
struct perf_hpp_fmt *fmt; struct perf_hpp_fmt *fmt;
struct perf_hpp_list *hpp_list;
struct hist_entry *parent_he; struct hist_entry *parent_he;
union { union {
/* this is for hierarchical entry structure */ /* this is for hierarchical entry structure */