perf tools: Skip elided sort entries
[deliverable/linux.git] / tools / perf / ui / browsers / hists.c
index 7ec871af3f6f8c5cc4796f40c14c801aa3ba3943..1c331b934ffc50747c1b6df0ba6658e81fe8971d 100644 (file)
@@ -26,13 +26,36 @@ struct hist_browser {
        int                  print_seq;
        bool                 show_dso;
        float                min_pcnt;
-       u64                  nr_pcnt_entries;
+       u64                  nr_non_filtered_entries;
+       u64                  nr_callchain_rows;
 };
 
 extern void hist_browser__init_hpp(void);
 
 static int hists__browser_title(struct hists *hists, char *bf, size_t size,
                                const char *ev_name);
+static void hist_browser__update_nr_entries(struct hist_browser *hb);
+
+static struct rb_node *hists__filter_entries(struct rb_node *nd,
+                                            struct hists *hists,
+                                            float min_pcnt);
+
+static bool hist_browser__has_filter(struct hist_browser *hb)
+{
+       return hists__has_filter(hb->hists) || hb->min_pcnt;
+}
+
+static u32 hist_browser__nr_entries(struct hist_browser *hb)
+{
+       u32 nr_entries;
+
+       if (hist_browser__has_filter(hb))
+               nr_entries = hb->nr_non_filtered_entries;
+       else
+               nr_entries = hb->hists->nr_entries;
+
+       return nr_entries + hb->nr_callchain_rows;
+}
 
 static void hist_browser__refresh_dimensions(struct hist_browser *browser)
 {
@@ -43,7 +66,14 @@ static void hist_browser__refresh_dimensions(struct hist_browser *browser)
 
 static void hist_browser__reset(struct hist_browser *browser)
 {
-       browser->b.nr_entries = browser->hists->nr_entries;
+       /*
+        * The hists__remove_entry_filter() already folds non-filtered
+        * entries so we can assume it has 0 callchain rows.
+        */
+       browser->nr_callchain_rows = 0;
+
+       hist_browser__update_nr_entries(browser);
+       browser->b.nr_entries = hist_browser__nr_entries(browser);
        hist_browser__refresh_dimensions(browser);
        ui_browser__reset_index(&browser->b);
 }
@@ -198,14 +228,16 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser)
                struct hist_entry *he = browser->he_selection;
 
                hist_entry__init_have_children(he);
-               browser->hists->nr_entries -= he->nr_rows;
+               browser->b.nr_entries -= he->nr_rows;
+               browser->nr_callchain_rows -= he->nr_rows;
 
                if (he->ms.unfolded)
                        he->nr_rows = callchain__count_rows(&he->sorted_chain);
                else
                        he->nr_rows = 0;
-               browser->hists->nr_entries += he->nr_rows;
-               browser->b.nr_entries = browser->hists->nr_entries;
+
+               browser->b.nr_entries += he->nr_rows;
+               browser->nr_callchain_rows += he->nr_rows;
 
                return true;
        }
@@ -280,23 +312,27 @@ static void hist_entry__set_folding(struct hist_entry *he, bool unfold)
                he->nr_rows = 0;
 }
 
-static void hists__set_folding(struct hists *hists, bool unfold)
+static void
+__hist_browser__set_folding(struct hist_browser *browser, bool unfold)
 {
        struct rb_node *nd;
+       struct hists *hists = browser->hists;
 
-       hists->nr_entries = 0;
-
-       for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
+       for (nd = rb_first(&hists->entries);
+            (nd = hists__filter_entries(nd, hists, browser->min_pcnt)) != NULL;
+            nd = rb_next(nd)) {
                struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
                hist_entry__set_folding(he, unfold);
-               hists->nr_entries += 1 + he->nr_rows;
+               browser->nr_callchain_rows += he->nr_rows;
        }
 }
 
 static void hist_browser__set_folding(struct hist_browser *browser, bool unfold)
 {
-       hists__set_folding(browser->hists, unfold);
-       browser->b.nr_entries = browser->hists->nr_entries;
+       browser->nr_callchain_rows = 0;
+       __hist_browser__set_folding(browser, unfold);
+
+       browser->b.nr_entries = hist_browser__nr_entries(browser);
        /* Go to the start, we may be way after valid entries after a collapse */
        ui_browser__reset_index(&browser->b);
 }
@@ -310,8 +346,6 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
                "Or reduce the sampling frequency.");
 }
 
-static void hist_browser__update_pcnt_entries(struct hist_browser *hb);
-
 static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
                             struct hist_browser_timer *hbt)
 {
@@ -320,9 +354,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
        int delay_secs = hbt ? hbt->refresh : 0;
 
        browser->b.entries = &browser->hists->entries;
-       browser->b.nr_entries = browser->hists->nr_entries;
-       if (browser->min_pcnt)
-               browser->b.nr_entries = browser->nr_pcnt_entries;
+       browser->b.nr_entries = hist_browser__nr_entries(browser);
 
        hist_browser__refresh_dimensions(browser);
        hists__browser_title(browser->hists, title, sizeof(title), ev_name);
@@ -339,13 +371,10 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
                        u64 nr_entries;
                        hbt->timer(hbt->arg);
 
-                       if (browser->min_pcnt) {
-                               hist_browser__update_pcnt_entries(browser);
-                               nr_entries = browser->nr_pcnt_entries;
-                       } else {
-                               nr_entries = browser->hists->nr_entries;
-                       }
+                       if (hist_browser__has_filter(browser))
+                               hist_browser__update_nr_entries(browser);
 
+                       nr_entries = hist_browser__nr_entries(browser);
                        ui_browser__update_nr_entries(&browser->b, nr_entries);
 
                        if (browser->hists->stats.nr_lost_warned !=
@@ -587,35 +616,6 @@ struct hpp_arg {
        bool current_entry;
 };
 
-static int __hpp__overhead_callback(struct perf_hpp *hpp, bool front)
-{
-       struct hpp_arg *arg = hpp->ptr;
-
-       if (arg->current_entry && arg->b->navkeypressed)
-               ui_browser__set_color(arg->b, HE_COLORSET_SELECTED);
-       else
-               ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
-
-       if (front) {
-               if (!symbol_conf.use_callchain)
-                       return 0;
-
-               slsmg_printf("%c ", arg->folded_sign);
-               return 2;
-       }
-
-       return 0;
-}
-
-static int __hpp__color_callback(struct perf_hpp *hpp, bool front __maybe_unused)
-{
-       struct hpp_arg *arg = hpp->ptr;
-
-       if (!arg->current_entry || !arg->b->navkeypressed)
-               ui_browser__set_color(arg->b, HE_COLORSET_NORMAL);
-       return 0;
-}
-
 static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
 {
        struct hpp_arg *arg = hpp->ptr;
@@ -636,7 +636,7 @@ static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
        return ret;
 }
 
-#define __HPP_COLOR_PERCENT_FN(_type, _field, _cb)                     \
+#define __HPP_COLOR_PERCENT_FN(_type, _field)                          \
 static u64 __hpp_get_##_field(struct hist_entry *he)                   \
 {                                                                      \
        return he->stat._field;                                         \
@@ -647,22 +647,20 @@ hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\
                                struct perf_hpp *hpp,                   \
                                struct hist_entry *he)                  \
 {                                                                      \
-       return __hpp__fmt(hpp, he, __hpp_get_##_field, _cb, " %6.2f%%", \
+       return __hpp__fmt(hpp, he, __hpp_get_##_field, " %6.2f%%",      \
                          __hpp__slsmg_color_printf, true);             \
 }
 
-__HPP_COLOR_PERCENT_FN(overhead, period, __hpp__overhead_callback)
-__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys, __hpp__color_callback)
-__HPP_COLOR_PERCENT_FN(overhead_us, period_us, __hpp__color_callback)
-__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys, __hpp__color_callback)
-__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, __hpp__color_callback)
+__HPP_COLOR_PERCENT_FN(overhead, period)
+__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
+__HPP_COLOR_PERCENT_FN(overhead_us, period_us)
+__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
+__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
 
 #undef __HPP_COLOR_PERCENT_FN
 
 void hist_browser__init_hpp(void)
 {
-       perf_hpp__init();
-
        perf_hpp__format[PERF_HPP__OVERHEAD].color =
                                hist_browser__hpp_color_overhead;
        perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color =
@@ -700,7 +698,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 
        if (row_offset == 0) {
                struct hpp_arg arg = {
-                       .b              = &browser->b,
+                       .b              = &browser->b,
                        .folded_sign    = folded_sign,
                        .current_entry  = current_entry,
                };
@@ -713,11 +711,27 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                ui_browser__gotorc(&browser->b, row, 0);
 
                perf_hpp__for_each_format(fmt) {
-                       if (!first) {
+                       if (perf_hpp__should_skip(fmt))
+                               continue;
+
+                       if (current_entry && browser->b.navkeypressed) {
+                               ui_browser__set_color(&browser->b,
+                                                     HE_COLORSET_SELECTED);
+                       } else {
+                               ui_browser__set_color(&browser->b,
+                                                     HE_COLORSET_NORMAL);
+                       }
+
+                       if (first) {
+                               if (symbol_conf.use_callchain) {
+                                       slsmg_printf("%c ", folded_sign);
+                                       width -= 2;
+                               }
+                               first = false;
+                       } else {
                                slsmg_printf("  ");
                                width -= 2;
                        }
-                       first = false;
 
                        if (fmt->color) {
                                width -= fmt->color(fmt, &hpp, entry);
@@ -731,8 +745,8 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                if (!browser->b.navkeypressed)
                        width += 1;
 
-               hist_entry__sort_snprintf(entry, s, sizeof(s), browser->hists);
-               slsmg_write_nstring(s, width);
+               slsmg_write_nstring("", width);
+
                ++row;
                ++printed;
        } else
@@ -769,12 +783,15 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
 
        for (nd = browser->top; nd; nd = rb_next(nd)) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
-               float percent = h->stat.period * 100.0 /
-                                       hb->hists->stats.total_period;
+               u64 total = hists__total_period(h->hists);
+               float percent = 0.0;
 
                if (h->filtered)
                        continue;
 
+               if (total)
+                       percent = h->stat.period * 100.0 / total;
+
                if (percent < hb->min_pcnt)
                        continue;
 
@@ -792,13 +809,13 @@ static struct rb_node *hists__filter_entries(struct rb_node *nd,
 {
        while (nd != NULL) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
-               float percent = h->stat.period * 100.0 /
-                                       hists->stats.total_period;
+               u64 total = hists__total_period(hists);
+               float percent = 0.0;
 
-               if (percent < min_pcnt)
-                       return NULL;
+               if (total)
+                       percent = h->stat.period * 100.0 / total;
 
-               if (!h->filtered)
+               if (!h->filtered && percent >= min_pcnt)
                        return nd;
 
                nd = rb_next(nd);
@@ -813,8 +830,11 @@ static struct rb_node *hists__filter_prev_entries(struct rb_node *nd,
 {
        while (nd != NULL) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
-               float percent = h->stat.period * 100.0 /
-                                       hists->stats.total_period;
+               u64 total = hists__total_period(hists);
+               float percent = 0.0;
+
+               if (total)
+                       percent = h->stat.period * 100.0 / total;
 
                if (!h->filtered && percent >= min_pcnt)
                        return nd;
@@ -1066,27 +1086,35 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
                                       struct hist_entry *he, FILE *fp)
 {
        char s[8192];
-       double percent;
        int printed = 0;
        char folded_sign = ' ';
+       struct perf_hpp hpp = {
+               .buf = s,
+               .size = sizeof(s),
+       };
+       struct perf_hpp_fmt *fmt;
+       bool first = true;
+       int ret;
 
        if (symbol_conf.use_callchain)
                folded_sign = hist_entry__folded(he);
 
-       hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists);
-       percent = (he->stat.period * 100.0) / browser->hists->stats.total_period;
-
        if (symbol_conf.use_callchain)
                printed += fprintf(fp, "%c ", folded_sign);
 
-       printed += fprintf(fp, " %5.2f%%", percent);
-
-       if (symbol_conf.show_nr_samples)
-               printed += fprintf(fp, " %11u", he->stat.nr_events);
+       perf_hpp__for_each_format(fmt) {
+               if (perf_hpp__should_skip(fmt))
+                       continue;
 
-       if (symbol_conf.show_total_period)
-               printed += fprintf(fp, " %12" PRIu64, he->stat.period);
+               if (!first) {
+                       ret = scnprintf(hpp.buf, hpp.size, "  ");
+                       advance_hpp(&hpp, ret);
+               } else
+                       first = false;
 
+               ret = fmt->entry(fmt, &hpp, he);
+               advance_hpp(&hpp, ret);
+       }
        printed += fprintf(fp, "%s\n", rtrim(s));
 
        if (folded_sign == '-')
@@ -1189,6 +1217,11 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
        char buf[512];
        size_t buflen = sizeof(buf);
 
+       if (symbol_conf.filter_relative) {
+               nr_samples = hists->stats.nr_non_filtered_samples;
+               nr_events = hists->stats.total_non_filtered_period;
+       }
+
        if (perf_evsel__is_group_event(evsel)) {
                struct perf_evsel *pos;
 
@@ -1196,8 +1229,13 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
                ev_name = buf;
 
                for_each_group_member(pos, evsel) {
-                       nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
-                       nr_events += pos->hists.stats.total_period;
+                       if (symbol_conf.filter_relative) {
+                               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;
+                       }
                }
        }
 
@@ -1324,18 +1362,23 @@ close_file_and_continue:
        return ret;
 }
 
-static void hist_browser__update_pcnt_entries(struct hist_browser *hb)
+static void hist_browser__update_nr_entries(struct hist_browser *hb)
 {
        u64 nr_entries = 0;
        struct rb_node *nd = rb_first(&hb->hists->entries);
 
-       while (nd) {
+       if (hb->min_pcnt == 0) {
+               hb->nr_non_filtered_entries = hb->hists->nr_non_filtered_entries;
+               return;
+       }
+
+       while ((nd = hists__filter_entries(nd, hb->hists,
+                                          hb->min_pcnt)) != NULL) {
                nr_entries++;
-               nd = hists__filter_entries(rb_next(nd), hb->hists,
-                                          hb->min_pcnt);
+               nd = rb_next(nd);
        }
 
-       hb->nr_pcnt_entries = nr_entries;
+       hb->nr_non_filtered_entries = nr_entries;
 }
 
 static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
@@ -1370,6 +1413,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
        "C             Collapse all callchains\n"                       \
        "d             Zoom into current DSO\n"                         \
        "E             Expand all callchains\n"                         \
+       "F             Toggle percentage of filtered entries\n"         \
 
        /* help messages are sorted by lexical order of the hotkey */
        const char report_help[] = HIST_BROWSER_HELP_COMMON
@@ -1391,7 +1435,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 
        if (min_pcnt) {
                browser->min_pcnt = min_pcnt;
-               hist_browser__update_pcnt_entries(browser);
+               hist_browser__update_nr_entries(browser);
        }
 
        fstack = pstack__new(2);
@@ -1475,6 +1519,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                        if (env->arch)
                                tui__header_window(env);
                        continue;
+               case 'F':
+                       symbol_conf.filter_relative ^= 1;
+                       continue;
                case K_F1:
                case 'h':
                case '?':
This page took 0.031365 seconds and 5 git commands to generate.