Skip to content

Commit

Permalink
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/jolsa/perf into perf/core

Pull perf/core improvements and fixes from Jiri Olsa:

  * Factor hists statistics counts processing which in turn also
    fixes several bugs in TUI report command (Namhyung Kim)

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Apr 25, 2014
2 parents 42ebd27 + c3b7895 commit 2933d78
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 103 deletions.
3 changes: 1 addition & 2 deletions tools/perf/builtin-annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct perf_annotate {
};

static int perf_evsel__add_sample(struct perf_evsel *evsel,
struct perf_sample *sample,
struct perf_sample *sample __maybe_unused,
struct addr_location *al,
struct perf_annotate *ann)
{
Expand All @@ -70,7 +70,6 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
return -ENOMEM;

ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
evsel->hists.stats.total_period += sample->period;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
return ret;
}
Expand Down
23 changes: 14 additions & 9 deletions tools/perf/builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,11 +341,16 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
return -1;
}

if (al.filtered == 0) {
evsel->hists.stats.total_non_filtered_period += sample->period;
evsel->hists.nr_non_filtered_entries++;
}
/*
* The total_period is updated here before going to the output
* tree since normally only the baseline hists will call
* hists__output_resort() and precompute needs the total
* period in order to sort entries by percentage delta.
*/
evsel->hists.stats.total_period += sample->period;
if (!al.filtered)
evsel->hists.stats.total_non_filtered_period += sample->period;

return 0;
}

Expand Down Expand Up @@ -573,10 +578,7 @@ static void hists__compute_resort(struct hists *hists)
hists->entries = RB_ROOT;
next = rb_first(root);

hists->nr_entries = 0;
hists->nr_non_filtered_entries = 0;
hists->stats.total_period = 0;
hists->stats.total_non_filtered_period = 0;
hists__reset_stats(hists);
hists__reset_col_len(hists);

while (next != NULL) {
Expand All @@ -586,7 +588,10 @@ static void hists__compute_resort(struct hists *hists)
next = rb_next(&he->rb_node_in);

insert_hist_entry_by_compute(&hists->entries, he, compute);
hists__inc_nr_entries(hists, he);
hists__inc_stats(hists, he);

if (!he->filtered)
hists__calc_col_len(hists, he);
}
}

Expand Down
64 changes: 31 additions & 33 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct report {
const char *cpu_list;
const char *symbol_filter_str;
float min_percent;
u64 nr_entries;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
};

Expand All @@ -75,6 +76,27 @@ static int report__config(const char *var, const char *value, void *cb)
return perf_default_config(var, value, cb);
}

static void report__inc_stats(struct report *rep, struct hist_entry *he)
{
/*
* The @he is either of a newly created one or an existing one
* merging current sample. We only want to count a new one so
* checking ->nr_events being 1.
*/
if (he->stat.nr_events == 1)
rep->nr_entries++;

/*
* Only counts number of samples at this stage as it's more
* natural to do it here and non-sample events are also
* counted in perf_session_deliver_event(). The dump_trace
* requires this info is ready before going to the output tree.
*/
hists__inc_nr_events(he->hists, PERF_RECORD_SAMPLE);
if (!he->filtered)
he->hists->stats.nr_non_filtered_samples++;
}

static int report__add_mem_hist_entry(struct report *rep, struct addr_location *al,
struct perf_sample *sample, struct perf_evsel *evsel)
{
Expand Down Expand Up @@ -121,10 +143,8 @@ static int report__add_mem_hist_entry(struct report *rep, struct addr_location *
goto out;
}

evsel->hists.stats.total_period += cost;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
if (!he->filtered)
evsel->hists.stats.nr_non_filtered_samples++;
report__inc_stats(rep, he);

err = hist_entry__append_callchain(he, sample);
out:
return err;
Expand Down Expand Up @@ -175,11 +195,7 @@ static int report__add_branch_hist_entry(struct report *rep, struct addr_locatio
if (err)
goto out;
}

evsel->hists.stats.total_period += 1;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
if (!he->filtered)
evsel->hists.stats.nr_non_filtered_samples++;
report__inc_stats(rep, he);
} else
goto out;
}
Expand Down Expand Up @@ -212,10 +228,8 @@ static int report__add_hist_entry(struct report *rep, struct perf_evsel *evsel,
if (ui__has_annotation())
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);

evsel->hists.stats.total_period += sample->period;
if (!he->filtered)
evsel->hists.stats.nr_non_filtered_samples++;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
report__inc_stats(rep, he);

out:
return err;
}
Expand Down Expand Up @@ -486,24 +500,12 @@ static int report__browse_hists(struct report *rep)
return ret;
}

static u64 report__collapse_hists(struct report *rep)
static void report__collapse_hists(struct report *rep)
{
struct ui_progress prog;
struct perf_evsel *pos;
u64 nr_samples = 0;
/*
* Count number of histogram entries to use when showing progress,
* reusing nr_samples variable.
*/
evlist__for_each(rep->session->evlist, pos)
nr_samples += pos->hists.nr_entries;

ui_progress__init(&prog, nr_samples, "Merging related events...");
/*
* Count total number of samples, will be used to check if this
* session had any.
*/
nr_samples = 0;
ui_progress__init(&prog, rep->nr_entries, "Merging related events...");

evlist__for_each(rep->session->evlist, pos) {
struct hists *hists = &pos->hists;
Expand All @@ -512,7 +514,6 @@ static u64 report__collapse_hists(struct report *rep)
hists->symbol_filter_str = rep->symbol_filter_str;

hists__collapse_resort(hists, &prog);
nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];

/* Non-group events are considered as leader */
if (symbol_conf.event_group &&
Expand All @@ -525,14 +526,11 @@ static u64 report__collapse_hists(struct report *rep)
}

ui_progress__finish();

return nr_samples;
}

static int __cmd_report(struct report *rep)
{
int ret;
u64 nr_samples;
struct perf_session *session = rep->session;
struct perf_evsel *pos;
struct perf_data_file *file = session->file;
Expand Down Expand Up @@ -572,12 +570,12 @@ static int __cmd_report(struct report *rep)
}
}

nr_samples = report__collapse_hists(rep);
report__collapse_hists(rep);

if (session_done())
return 0;

if (nr_samples == 0) {
if (rep->nr_entries == 0) {
ui__error("The %s file has no samples!\n", file->path);
return 0;
}
Expand Down
92 changes: 63 additions & 29 deletions tools/perf/ui/browsers/hists.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
}
Expand All @@ -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)
{
Expand All @@ -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);
Expand All @@ -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 !=
Expand Down Expand Up @@ -1343,18 +1372,23 @@ static int switch_data_file(void)
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,
Expand Down Expand Up @@ -1411,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);
Expand Down
Loading

0 comments on commit 2933d78

Please sign in to comment.