perf hists: Use own hpp_list for hierarchy mode
authorNamhyung Kim <namhyung@kernel.org>
Mon, 7 Mar 2016 19:44:46 +0000 (16:44 -0300)
committerIngo Molnar <mingo@kernel.org>
Tue, 8 Mar 2016 09:11:19 +0000 (10:11 +0100)
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>
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/hists.c
tools/perf/ui/hist.c
tools/perf/ui/stdio/hist.c
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/sort.h

index 5ffffcb1e3c56e18511d7bae4ce6d5f117976336..928b4825b752b18c3d85c177d5168e4d88e77edb 100644 (file)
@@ -1388,25 +1388,26 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
                                              HE_COLORSET_NORMAL);
                }
 
-               ui_browser__write_nstring(&browser->b, "", 2);
-               width -= 2;
+               perf_hpp_list__for_each_format(entry->hpp_list, fmt) {
+                       ui_browser__write_nstring(&browser->b, "", 2);
+                       width -= 2;
 
-               /*
-                * No need to call hist_entry__snprintf_alignment()
-                * since this fmt is always the last column in the
-                * hierarchy mode.
-                */
-               fmt = entry->fmt;
-               if (fmt->color) {
-                       width -= fmt->color(fmt, &hpp, entry);
-               } else {
-                       int i = 0;
+                       /*
+                        * No need to call hist_entry__snprintf_alignment()
+                        * since this fmt is always the last column in the
+                        * hierarchy mode.
+                        */
+                       if (fmt->color) {
+                               width -= fmt->color(fmt, &hpp, entry);
+                       } else {
+                               int i = 0;
 
-                       width -= fmt->entry(fmt, &hpp, entry);
-                       ui_browser__printf(&browser->b, "%s", ltrim(s));
+                               width -= fmt->entry(fmt, &hpp, entry);
+                               ui_browser__printf(&browser->b, "%s", ltrim(s));
 
-                       while (isspace(s[i++]))
-                               width++;
+                               while (isspace(s[i++]))
+                                       width++;
+                       }
                }
        }
 
@@ -1934,7 +1935,7 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
        struct perf_hpp_fmt *fmt;
        bool first = true;
        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, "");
 
@@ -1962,9 +1963,13 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
        ret = scnprintf(hpp.buf, hpp.size, "%*s", hierarchy_indent, "");
        advance_hpp(&hpp, ret);
 
-       fmt = he->fmt;
-       ret = fmt->entry(fmt, &hpp, he);
-       advance_hpp(&hpp, ret);
+       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);
+               advance_hpp(&hpp, ret);
+       }
 
        printed += fprintf(fp, "%s\n", rtrim(s));
 
index a5758fdfbe1fe0f5a16e738fda69e3942595d4da..4534e2d7669c1df8b7db861e8e577b81b15cec29 100644 (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)) {
                GtkTreeIter iter;
                float percent;
+               char *bf;
 
                he = rb_entry(node, struct hist_entry, rb_node);
                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);
                }
 
-               fmt = he->fmt;
-               if (fmt->color)
-                       fmt->color(fmt, hpp, he);
-               else
-                       fmt->entry(fmt, hpp, he);
+               bf = hpp->buf;
+               perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+                       int ret;
+
+                       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(hpp->buf), -1);
+               gtk_tree_store_set(store, &iter, col_idx, rtrim(bf), -1);
 
                if (!he->leaf) {
                        perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,
index 3a15e844f89a8e736c6a95a079f1e296347c28ff..95795ef4209b9018c164f41c3370bb5e54d5620e 100644 (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_fmt *fmt_copy;
        bool found = false;
+       bool skip = perf_hpp__should_skip(fmt, hists);
 
        list_for_each_entry(node, &hists->hpp_formats, list) {
                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)
                        return -1;
 
+               node->skip = skip;
                node->level = fmt->level;
                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)
                return -1;
 
+       if (!skip)
+               node->skip = false;
+
        list_add_tail(&fmt_copy->list, &node->hpp.fields);
        list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts);
 
index 6d06fbb365b6a9f896ff4f251fb36a2586009758..073642a63cc9480292ad3e8637833dcddecd5be4 100644 (file)
@@ -451,33 +451,33 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
                advance_hpp(hpp, ret);
        }
 
-       if (sep)
-               ret = scnprintf(hpp->buf, hpp->size, "%s", sep);
-       else
+       if (!sep)
                ret = scnprintf(hpp->buf, hpp->size, "%*s",
-                               (nr_sort_key - 1) * HIERARCHY_INDENT + 2, "");
+                               (nr_sort_key - 1) * HIERARCHY_INDENT, "");
        advance_hpp(hpp, ret);
 
        printed += fprintf(fp, "%s", buf);
 
-       hpp->buf  = buf;
-       hpp->size = size;
-
-       /*
-        * No need to call hist_entry__snprintf_alignment() since this
-        * fmt is always the last column in the hierarchy mode.
-        */
-       fmt = he->fmt;
-       if (perf_hpp__use_color() && fmt->color)
-               fmt->color(fmt, hpp, he);
-       else
-               fmt->entry(fmt, hpp, he);
-
-       /*
-        * dynamic entries are right-aligned but we want left-aligned
-        * in the hierarchy mode
-        */
-       printed += fprintf(fp, "%s\n", ltrim(buf));
+       perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+               hpp->buf  = buf;
+               hpp->size = size;
+
+               /*
+                * No need to call hist_entry__snprintf_alignment() since this
+                * fmt is always the last column in the hierarchy mode.
+                */
+               if (perf_hpp__use_color() && fmt->color)
+                       fmt->color(fmt, hpp, he);
+               else
+                       fmt->entry(fmt, hpp, he);
+
+               /*
+                * dynamic entries are right-aligned but we want left-aligned
+                * in the hierarchy mode
+                */
+               printed += fprintf(fp, "%s%s", sep ?: "  ", ltrim(buf));
+       }
+       printed += putc('\n', fp);
 
        if (symbol_conf.use_callchain && he->leaf) {
                u64 total = hists__total_period(hists);
index fea92fcb6903f0da4c2d1a4506f489b5517c313e..29da9e0d8db90591e8c3c82798a5f06713dcd5d8 100644 (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,
                                                 struct rb_root *root,
                                                 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 *parent = NULL;
        struct hist_entry *iter, *new;
+       struct perf_hpp_fmt *fmt;
        int64_t cmp;
 
        while (*p != NULL) {
                parent = *p;
                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) {
                        he_stat__add_stat(&iter->stat, &he->stat);
                        return iter;
@@ -1121,24 +1128,26 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
        hists__apply_filters(hists, new);
        hists->nr_entries++;
 
-       /* save related format for output */
-       new->fmt = fmt;
+       /* save related format list for output */
+       new->hpp_list = hpp_list;
 
        /* some fields are now passed to 'new' */
-       if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
-               he->trace_output = NULL;
-       else
-               new->trace_output = NULL;
+       perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
+               if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
+                       he->trace_output = NULL;
+               else
+                       new->trace_output = NULL;
 
-       if (perf_hpp__is_srcline_entry(fmt))
-               he->srcline = NULL;
-       else
-               new->srcline = NULL;
+               if (perf_hpp__is_srcline_entry(fmt))
+                       he->srcline = NULL;
+               else
+                       new->srcline = NULL;
 
-       if (perf_hpp__is_srcfile_entry(fmt))
-               he->srcfile = NULL;
-       else
-               new->srcfile = NULL;
+               if (perf_hpp__is_srcfile_entry(fmt))
+                       he->srcfile = NULL;
+               else
+                       new->srcfile = NULL;
+       }
 
        rb_link_node(&new->rb_node_in, parent, p);
        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 hist_entry *he)
 {
-       struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *node;
        struct hist_entry *new_he = NULL;
        struct hist_entry *parent = NULL;
        int depth = 0;
        int ret = 0;
 
-       hists__for_each_sort_list(hists, fmt) {
-               if (!perf_hpp__is_sort_entry(fmt) &&
-                   !perf_hpp__is_dynamic_entry(fmt))
-                       continue;
-               if (perf_hpp__should_skip(fmt, hists))
+       list_for_each_entry(node, &hists->hpp_formats, list) {
+               /* skip period (overhead) and elided columns */
+               if (node->level == 0 || node->skip)
                        continue;
 
                /* 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) {
                        ret = -1;
                        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 *parent = NULL;
        struct hist_entry *iter;
+       struct perf_hpp_fmt *fmt;
 
        while (*p != NULL) {
                parent = *p;
@@ -1373,8 +1381,10 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
        rb_insert_color(&he->rb_node, root);
 
        /* update column width of dynamic entry */
-       if (perf_hpp__is_dynamic_entry(he->fmt))
-               he->fmt->sort(he->fmt, he, NULL);
+       perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
+               if (perf_hpp__is_dynamic_entry(fmt))
+                       fmt->sort(fmt, he, NULL);
+       }
 }
 
 static void hists__hierarchy_output_resort(struct hists *hists,
index 3cab9dc20822cb10824d48d0d5c1b808a007623f..2209188d729c83295045eac8f0233b6a8bcd14b1 100644 (file)
@@ -249,6 +249,7 @@ struct perf_hpp_list_node {
        struct list_head        list;
        struct perf_hpp_list    hpp;
        int                     level;
+       bool                    skip;
 };
 
 void perf_hpp_list__column_register(struct perf_hpp_list *list,
index 25a5529a94e484dd704f535746848acbf0439cc8..ea1f722cffea73d4ad47a63178d570ce7195d874 100644 (file)
@@ -130,6 +130,7 @@ struct hist_entry {
        u32                     raw_size;
        void                    *trace_output;
        struct perf_hpp_fmt     *fmt;
+       struct perf_hpp_list    *hpp_list;
        struct hist_entry       *parent_he;
        union {
                /* this is for hierarchical entry structure */