perf tools: Fix column width setting on 'trace' sort key
[deliverable/linux.git] / tools / perf / util / hist.c
index 098310bc44893c16a8dcea649c0560a40d099d5e..017eb5c42c37edffc0fb128207c21d40d9ba1587 100644 (file)
@@ -179,6 +179,9 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
        if (h->transaction)
                hists__new_col_len(hists, HISTC_TRANSACTION,
                                   hist_entry__transaction_len());
+
+       if (h->trace_output)
+               hists__new_col_len(hists, HISTC_TRACE, strlen(h->trace_output));
 }
 
 void hists__output_recalc_col_len(struct hists *hists, int max_rows)
@@ -405,6 +408,16 @@ static u8 symbol__parent_filter(const struct symbol *parent)
        return 0;
 }
 
+static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period)
+{
+       if (!symbol_conf.use_callchain)
+               return;
+
+       he->hists->callchain_period += period;
+       if (!he->filtered)
+               he->hists->callchain_non_filtered_period += period;
+}
+
 static struct hist_entry *hists__findnew_entry(struct hists *hists,
                                               struct hist_entry *entry,
                                               struct addr_location *al,
@@ -434,9 +447,7 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
                if (!cmp) {
                        if (sample_self) {
                                he_stat__add_period(&he->stat, period, weight);
-                               hists->stats.total_period += period;
-                               if (!he->filtered)
-                                       hists->stats.total_non_filtered_period += period;
+                               hist_entry__add_callchain_period(he, period);
                        }
                        if (symbol_conf.cumulate_callchain)
                                he_stat__add_period(he->stat_acc, period, weight);
@@ -471,9 +482,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
                return NULL;
 
        if (sample_self)
-               hists__inc_stats(hists, he);
-       else
-               hists->nr_entries++;
+               hist_entry__add_callchain_period(he, period);
+       hists->nr_entries++;
 
        rb_link_node(&he->rb_node_in, parent, p);
        rb_insert_color(&he->rb_node_in, hists->entries_in);
@@ -958,10 +968,11 @@ out:
 int64_t
 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
 {
+       struct hists *hists = left->hists;
        struct perf_hpp_fmt *fmt;
        int64_t cmp = 0;
 
-       perf_hpp__for_each_sort_list(fmt) {
+       hists__for_each_sort_list(hists, fmt) {
                cmp = fmt->cmp(fmt, left, right);
                if (cmp)
                        break;
@@ -973,10 +984,11 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
 int64_t
 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
 {
+       struct hists *hists = left->hists;
        struct perf_hpp_fmt *fmt;
        int64_t cmp = 0;
 
-       perf_hpp__for_each_sort_list(fmt) {
+       hists__for_each_sort_list(hists, fmt) {
                cmp = fmt->collapse(fmt, left, right);
                if (cmp)
                        break;
@@ -1012,12 +1024,33 @@ void hist_entry__delete(struct hist_entry *he)
        free(he);
 }
 
+/*
+ * If this is not the last column, then we need to pad it according to the
+ * pre-calculated max lenght for this column, otherwise don't bother adding
+ * spaces because that would break viewing this with, for instance, 'less',
+ * that would show tons of trailing spaces when a long C++ demangled method
+ * names is sampled.
+*/
+int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
+                                  struct perf_hpp_fmt *fmt, int printed)
+{
+       if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) {
+               const int width = fmt->width(fmt, hpp, hists_to_evsel(he->hists));
+               if (printed < width) {
+                       advance_hpp(hpp, printed);
+                       printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " ");
+               }
+       }
+
+       return printed;
+}
+
 /*
  * collapse the histogram
  */
 
-bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
-                                 struct rb_root *root, struct hist_entry *he)
+int hists__collapse_insert_entry(struct hists *hists, struct rb_root *root,
+                                struct hist_entry *he)
 {
        struct rb_node **p = &root->rb_node;
        struct rb_node *parent = NULL;
@@ -1031,18 +1064,21 @@ bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
                cmp = hist_entry__collapse(iter, he);
 
                if (!cmp) {
+                       int ret = 0;
+
                        he_stat__add_stat(&iter->stat, &he->stat);
                        if (symbol_conf.cumulate_callchain)
                                he_stat__add_stat(iter->stat_acc, he->stat_acc);
 
                        if (symbol_conf.use_callchain) {
                                callchain_cursor_reset(&callchain_cursor);
-                               callchain_merge(&callchain_cursor,
-                                               iter->callchain,
-                                               he->callchain);
+                               if (callchain_merge(&callchain_cursor,
+                                                   iter->callchain,
+                                                   he->callchain) < 0)
+                                       ret = -1;
                        }
                        hist_entry__delete(he);
-                       return false;
+                       return ret;
                }
 
                if (cmp < 0)
@@ -1054,7 +1090,7 @@ bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
 
        rb_link_node(&he->rb_node_in, parent, p);
        rb_insert_color(&he->rb_node_in, root);
-       return true;
+       return 1;
 }
 
 struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
@@ -1080,14 +1116,15 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
        hists__filter_entry_by_socket(hists, he);
 }
 
-void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
+int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
 {
        struct rb_root *root;
        struct rb_node *next;
        struct hist_entry *n;
+       int ret;
 
        if (!sort__need_collapse)
-               return;
+               return 0;
 
        hists->nr_entries = 0;
 
@@ -1102,7 +1139,11 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
                next = rb_next(&n->rb_node_in);
 
                rb_erase(&n->rb_node_in, root);
-               if (hists__collapse_insert_entry(hists, &hists->entries_collapsed, n)) {
+               ret = hists__collapse_insert_entry(hists, &hists->entries_collapsed, n);
+               if (ret < 0)
+                       return -1;
+
+               if (ret) {
                        /*
                         * If it wasn't combined with one of the entries already
                         * collapsed, we need to apply the filters that may have
@@ -1113,14 +1154,16 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
                if (prog)
                        ui_progress__update(prog, 1);
        }
+       return 0;
 }
 
 static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
 {
+       struct hists *hists = a->hists;
        struct perf_hpp_fmt *fmt;
        int64_t cmp = 0;
 
-       perf_hpp__for_each_sort_list(fmt) {
+       hists__for_each_sort_list(hists, fmt) {
                if (perf_hpp__should_skip(fmt, a->hists))
                        continue;
 
@@ -1197,21 +1240,20 @@ static void __hists__insert_output_entry(struct rb_root *entries,
        rb_insert_color(&he->rb_node, entries);
 }
 
-void hists__output_resort(struct hists *hists, struct ui_progress *prog)
+static void output_resort(struct hists *hists, struct ui_progress *prog,
+                         bool use_callchain)
 {
        struct rb_root *root;
        struct rb_node *next;
        struct hist_entry *n;
+       u64 callchain_total;
        u64 min_callchain_hits;
-       struct perf_evsel *evsel = hists_to_evsel(hists);
-       bool use_callchain;
 
-       if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph)
-               use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN;
-       else
-               use_callchain = symbol_conf.use_callchain;
+       callchain_total = hists->callchain_period;
+       if (symbol_conf.filter_relative)
+               callchain_total = hists->callchain_non_filtered_period;
 
-       min_callchain_hits = hists__total_period(hists) * (callchain_param.min_percent / 100);
+       min_callchain_hits = callchain_total * (callchain_param.min_percent / 100);
 
        if (sort__need_collapse)
                root = &hists->entries_collapsed;
@@ -1239,6 +1281,23 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog)
        }
 }
 
+void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog)
+{
+       bool use_callchain;
+
+       if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph)
+               use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN;
+       else
+               use_callchain = symbol_conf.use_callchain;
+
+       output_resort(evsel__hists(evsel), prog, use_callchain);
+}
+
+void hists__output_resort(struct hists *hists, struct ui_progress *prog)
+{
+       output_resort(hists, prog, symbol_conf.use_callchain);
+}
+
 static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
                                       enum hist_filter filter)
 {
@@ -1567,7 +1626,7 @@ int perf_hist_config(const char *var, const char *value)
        return 0;
 }
 
-int __hists__init(struct hists *hists)
+int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list)
 {
        memset(hists, 0, sizeof(*hists));
        hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
@@ -1576,6 +1635,7 @@ int __hists__init(struct hists *hists)
        hists->entries = RB_ROOT;
        pthread_mutex_init(&hists->lock, NULL);
        hists->socket_filter = -1;
+       hists->hpp_list = hpp_list;
        return 0;
 }
 
@@ -1612,7 +1672,7 @@ static int hists_evsel__init(struct perf_evsel *evsel)
 {
        struct hists *hists = evsel__hists(evsel);
 
-       __hists__init(hists);
+       __hists__init(hists, &perf_hpp_list);
        return 0;
 }
 
@@ -1631,3 +1691,9 @@ int hists__init(void)
 
        return err;
 }
+
+void perf_hpp_list__init(struct perf_hpp_list *list)
+{
+       INIT_LIST_HEAD(&list->fields);
+       INIT_LIST_HEAD(&list->sorts);
+}
This page took 0.029436 seconds and 5 git commands to generate.