]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - tools/perf/ui/browsers/hists.c
perf hists/tui: Count callchain rows separately
[karo-tx-linux.git] / tools / perf / ui / browsers / hists.c
index 7ec871af3f6f8c5cc4796f40c14c801aa3ba3943..b0861e3e50a58c94955d77241e3a72528df6edc3 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 !=
@@ -769,12 +798,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,8 +824,11 @@ 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 (total)
+                       percent = h->stat.period * 100.0 / total;
 
                if (percent < min_pcnt)
                        return NULL;
@@ -813,8 +848,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;
@@ -1189,6 +1227,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 +1239,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 +1372,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 +1423,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 +1445,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 +1529,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 '?':