mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-05 10:56:48 +07:00
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:
parent
c3bc0c4368
commit
1b2dbbf41a
@ -1388,6 +1388,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
|
|||||||
HE_COLORSET_NORMAL);
|
HE_COLORSET_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
perf_hpp_list__for_each_format(entry->hpp_list, fmt) {
|
||||||
ui_browser__write_nstring(&browser->b, "", 2);
|
ui_browser__write_nstring(&browser->b, "", 2);
|
||||||
width -= 2;
|
width -= 2;
|
||||||
|
|
||||||
@ -1396,7 +1397,6 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
|
|||||||
* 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 {
|
||||||
@ -1409,6 +1409,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
|
|||||||
width++;
|
width++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The scroll bar isn't being used */
|
/* The scroll bar isn't being used */
|
||||||
if (!browser->b.navkeypressed)
|
if (!browser->b.navkeypressed)
|
||||||
@ -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 = scnprintf(hpp.buf, hpp.size, " ");
|
||||||
|
advance_hpp(&hpp, ret);
|
||||||
|
|
||||||
ret = fmt->entry(fmt, &hpp, he);
|
ret = fmt->entry(fmt, &hpp, he);
|
||||||
advance_hpp(&hpp, ret);
|
advance_hpp(&hpp, ret);
|
||||||
|
}
|
||||||
|
|
||||||
printed += fprintf(fp, "%s\n", rtrim(s));
|
printed += fprintf(fp, "%s\n", rtrim(s));
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -451,15 +451,14 @@ 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);
|
||||||
|
|
||||||
|
perf_hpp_list__for_each_format(he->hpp_list, fmt) {
|
||||||
hpp->buf = buf;
|
hpp->buf = buf;
|
||||||
hpp->size = size;
|
hpp->size = size;
|
||||||
|
|
||||||
@ -467,7 +466,6 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
|
|||||||
* 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
|
||||||
@ -477,7 +475,9 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *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);
|
||||||
|
@ -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 = 0;
|
||||||
|
perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
|
||||||
cmp = fmt->collapse(fmt, iter, he);
|
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,10 +1128,11 @@ 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' */
|
||||||
|
perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
|
||||||
if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
|
if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
|
||||||
he->trace_output = NULL;
|
he->trace_output = NULL;
|
||||||
else
|
else
|
||||||
@ -1139,6 +1147,7 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
|
|||||||
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,
|
||||||
|
@ -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,
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user