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)
{
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);
}
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;
}
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);
}
"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)
{
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);
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 !=
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;
{
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;
{
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;
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;
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;
+ }
}
}
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,
"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
if (min_pcnt) {
browser->min_pcnt = min_pcnt;
- hist_browser__update_pcnt_entries(browser);
+ hist_browser__update_nr_entries(browser);
}
fstack = pstack__new(2);
if (env->arch)
tui__header_window(env);
continue;
+ case 'F':
+ symbol_conf.filter_relative ^= 1;
+ continue;
case K_F1:
case 'h':
case '?':