perf hists browser: Print overhead percent value for first-level callchain
[cascardo/linux.git] / tools / perf / ui / browsers / hists.c
index 8f60a97..8d22905 100644 (file)
@@ -35,7 +35,9 @@ struct hist_browser {
 
 extern void hist_browser__init_hpp(void);
 
-static int hists__browser_title(struct hists *hists, char *bf, size_t size);
+static int hists__browser_title(struct hists *hists,
+                               struct hist_browser_timer *hbt,
+                               char *bf, size_t size);
 static void hist_browser__update_nr_entries(struct hist_browser *hb);
 
 static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -390,7 +392,7 @@ static int hist_browser__run(struct hist_browser *browser,
        browser->b.entries = &browser->hists->entries;
        browser->b.nr_entries = hist_browser__nr_entries(browser);
 
-       hists__browser_title(browser->hists, title, sizeof(title));
+       hists__browser_title(browser->hists, hbt, title, sizeof(title));
 
        if (ui_browser__show(&browser->b, title,
                             "Press '?' for help on key bindings") < 0)
@@ -417,7 +419,8 @@ static int hist_browser__run(struct hist_browser *browser,
                                ui_browser__warn_lost_events(&browser->b);
                        }
 
-                       hists__browser_title(browser->hists, title, sizeof(title));
+                       hists__browser_title(browser->hists,
+                                            hbt, title, sizeof(title));
                        ui_browser__show_title(&browser->b, title);
                        continue;
                }
@@ -460,23 +463,6 @@ out:
        return key;
 }
 
-static char *callchain_list__sym_name(struct callchain_list *cl,
-                                     char *bf, size_t bfsize, bool show_dso)
-{
-       int printed;
-
-       if (cl->ms.sym)
-               printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
-       else
-               printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
-
-       if (show_dso)
-               scnprintf(bf + printed, bfsize - printed, " %s",
-                         cl->ms.map ? cl->ms.map->dso->short_name : "unknown");
-
-       return bf;
-}
-
 struct callchain_print_arg {
        /* for hists browser */
        off_t   row_offset;
@@ -556,8 +542,11 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
        struct rb_node *node;
        int first_row = row, offset = level * LEVEL_OFFSET_STEP;
        u64 new_total;
+       bool need_percent;
 
        node = rb_first(root);
+       need_percent = !!rb_next(node);
+
        while (node) {
                struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
                struct rb_node *next = rb_next(node);
@@ -574,7 +563,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
 
                        if (first)
                                first = false;
-                       else if (level > 1)
+                       else if (need_percent)
                                extra_offset = LEVEL_OFFSET_STEP;
 
                        folded_sign = callchain_list__folded(chain);
@@ -587,7 +576,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
                        str = callchain_list__sym_name(chain, bf, sizeof(bf),
                                                       browser->show_dso);
 
-                       if (was_first && level > 1) {
+                       if (was_first && need_percent) {
                                double percent = cumul * 100.0 / total;
 
                                if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
@@ -804,6 +793,13 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                        .is_current_entry = current_entry,
                };
 
+               if (callchain_param.mode == CHAIN_GRAPH_REL) {
+                       if (symbol_conf.cumulate_callchain)
+                               total = entry->stat_acc->period;
+                       else
+                               total = entry->stat.period;
+               }
+
                printed += hist_browser__show_callchain(browser,
                                        &entry->sorted_chain, 1, row, total,
                                        hist_browser__show_callchain_entry, &arg,
@@ -1204,7 +1200,15 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *browser
        return browser->he_selection->thread;
 }
 
-static int hists__browser_title(struct hists *hists, char *bf, size_t size)
+/* Check whether the browser is for 'top' or 'report' */
+static inline bool is_report_browser(void *timer)
+{
+       return timer == NULL;
+}
+
+static int hists__browser_title(struct hists *hists,
+                               struct hist_browser_timer *hbt,
+                               char *bf, size_t size)
 {
        char unit;
        int printed;
@@ -1229,12 +1233,14 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size)
                ev_name = buf;
 
                for_each_group_member(pos, evsel) {
+                       struct hists *pos_hists = evsel__hists(pos);
+
                        if (symbol_conf.filter_relative) {
-                               nr_samples += pos->hists.stats.nr_non_filtered_samples;
-                               nr_events += pos->hists.stats.total_non_filtered_period;
+                               nr_samples += pos_hists->stats.nr_non_filtered_samples;
+                               nr_events += pos_hists->stats.total_non_filtered_period;
                        } else {
-                               nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
-                               nr_events += pos->hists.stats.total_period;
+                               nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
+                               nr_events += pos_hists->stats.total_period;
                        }
                }
        }
@@ -1256,6 +1262,13 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size)
        if (dso)
                printed += scnprintf(bf + printed, size - printed,
                                    ", DSO: %s", dso->short_name);
+       if (!is_report_browser(hbt)) {
+               struct perf_top *top = hbt->arg;
+
+               if (top->zero)
+                       printed += scnprintf(bf + printed, size - printed, " [z]");
+       }
+
        return printed;
 }
 
@@ -1267,12 +1280,6 @@ static inline void free_popup_options(char **options, int n)
                zfree(&options[i]);
 }
 
-/* Check whether the browser is for 'top' or 'report' */
-static inline bool is_report_browser(void *timer)
-{
-       return timer == NULL;
-}
-
 /*
  * Only runtime switching of perf data file will make "input_name" point
  * to a malloced buffer. So add "is_input_name_malloced" flag to decide
@@ -1387,7 +1394,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                                    float min_pcnt,
                                    struct perf_session_env *env)
 {
-       struct hists *hists = &evsel->hists;
+       struct hists *hists = evsel__hists(evsel);
        struct hist_browser *browser = hist_browser__new(hists);
        struct branch_info *bi;
        struct pstack *fstack;
@@ -1802,8 +1809,9 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
        struct perf_evsel_menu *menu = container_of(browser,
                                                    struct perf_evsel_menu, b);
        struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
+       struct hists *hists = evsel__hists(evsel);
        bool current_entry = ui_browser__is_current_entry(browser, row);
-       unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+       unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE];
        const char *ev_name = perf_evsel__name(evsel);
        char bf[256], unit;
        const char *warn = " ";
@@ -1818,7 +1826,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
                ev_name = perf_evsel__group_name(evsel);
 
                for_each_group_member(pos, evsel) {
-                       nr_events += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+                       struct hists *pos_hists = evsel__hists(pos);
+                       nr_events += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
                }
        }
 
@@ -1827,7 +1836,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
                           unit, unit == ' ' ? "" : " ", ev_name);
        slsmg_printf("%s", bf);
 
-       nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST];
+       nr_events = hists->stats.nr_events[PERF_RECORD_LOST];
        if (nr_events != 0) {
                menu->lost_events = true;
                if (!current_entry)