Skip to content

Commit

Permalink
perf report: Report number of events, not samples
Browse files Browse the repository at this point in the history
Number of samples is meaningless after we switched to auto-freq, so
report the number of events, i.e. not the sum of the different periods,
but the number PERF_RECORD_SAMPLE emitted by the kernel.

While doing this I noticed that naming "count" to the sum of all the
event periods can be confusing, so rename it to .period, just like in
struct sample.data, so that we become more consistent.

This helps with the next step, that was to record in struct hist_entry
the number of sample events for each instance, we need that because we
use it to generate the number of events when applying filters to the
tree of hist entries like it is being done in the TUI report browser.

Suggested-by: Ingo Molnar <mingo@elte.hu>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Arnaldo Carvalho de Melo committed May 14, 2010
1 parent cee75ac commit c82ee82
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 63 deletions.
6 changes: 3 additions & 3 deletions tools/perf/builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ static bool force;
static bool show_displacement;

static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 count)
struct addr_location *al, u64 period)
{
if (__hists__add_entry(self, al, NULL, count) != NULL)
if (__hists__add_entry(self, al, NULL, period) != NULL)
return 0;
return -ENOMEM;
}
Expand All @@ -50,7 +50,7 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi
event__parse_sample(event, session->sample_type, &data);

if (hists__add_entry(&session->hists, &al, data.period)) {
pr_warning("problem incrementing symbol count, skipping event\n");
pr_warning("problem incrementing symbol period, skipping event\n");
return -1;
}

Expand Down
32 changes: 22 additions & 10 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,14 @@ static int process_sample_event(event_t *event, struct perf_session *session)
return 0;

if (perf_session__add_hist_entry(session, &al, &data)) {
pr_debug("problem incrementing symbol count, skipping event\n");
pr_debug("problem incrementing symbol period, skipping event\n");
return -1;
}

attr = perf_header__find_attr(data.id, &session->header);

if (add_event_total(session, &data, attr)) {
pr_debug("problem adding event count\n");
pr_debug("problem adding event period\n");
return -1;
}

Expand Down Expand Up @@ -269,11 +269,25 @@ static struct perf_event_ops event_ops = {

extern volatile int session_done;

static void sig_handler(int sig __attribute__((__unused__)))
static void sig_handler(int sig __used)
{
session_done = 1;
}

static size_t hists__fprintf_nr_sample_events(struct hists *self,
const char *evname, FILE *fp)
{
size_t ret;
char unit;
unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE];

nr_events = convert_unit(nr_events, &unit);
ret = fprintf(fp, "# Events: %lu%c", nr_events, unit);
if (evname != NULL)
ret += fprintf(fp, " %s", evname);
return ret + fprintf(fp, "\n#\n");
}

static int __cmd_report(void)
{
int ret = -EINVAL;
Expand Down Expand Up @@ -319,14 +333,12 @@ static int __cmd_report(void)
if (use_browser)
hists__browse(hists, help, input_name);
else {
if (rb_first(&session->hists.entries) ==
const char *evname = NULL;
if (rb_first(&session->hists.entries) !=
rb_last(&session->hists.entries))
fprintf(stdout, "# Samples: %Ld\n#\n",
hists->stats.total_period);
else
fprintf(stdout, "# Samples: %Ld %s\n#\n",
hists->stats.total_period,
__event_name(hists->type, hists->config));
evname = __event_name(hists->type, hists->config);

hists__fprintf_nr_sample_events(hists, evname, stdout);

hists__fprintf(hists, NULL, false, stdout);
fprintf(stdout, "\n\n");
Expand Down
88 changes: 47 additions & 41 deletions tools/perf/util/hist.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,29 @@ struct callchain_param callchain_param = {
.min_percent = 0.5
};

static void hist_entry__add_cpumode_count(struct hist_entry *self,
unsigned int cpumode, u64 count)
static void hist_entry__add_cpumode_period(struct hist_entry *self,
unsigned int cpumode, u64 period)
{
switch (cpumode) {
case PERF_RECORD_MISC_KERNEL:
self->count_sys += count;
self->period_sys += period;
break;
case PERF_RECORD_MISC_USER:
self->count_us += count;
self->period_us += period;
break;
case PERF_RECORD_MISC_GUEST_KERNEL:
self->count_guest_sys += count;
self->period_guest_sys += period;
break;
case PERF_RECORD_MISC_GUEST_USER:
self->count_guest_us += count;
self->period_guest_us += period;
break;
default:
break;
}
}

/*
* histogram, sorted on item, collects counts
* histogram, sorted on item, collects periods
*/

static struct hist_entry *hist_entry__new(struct hist_entry *template)
Expand All @@ -41,6 +41,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)

if (self != NULL) {
*self = *template;
self->nr_events = 1;
if (symbol_conf.use_callchain)
callchain_init(self->callchain);
}
Expand All @@ -57,7 +58,7 @@ static void hists__inc_nr_entries(struct hists *self, struct hist_entry *entry)

struct hist_entry *__hists__add_entry(struct hists *self,
struct addr_location *al,
struct symbol *sym_parent, u64 count)
struct symbol *sym_parent, u64 period)
{
struct rb_node **p = &self->entries.rb_node;
struct rb_node *parent = NULL;
Expand All @@ -70,7 +71,7 @@ struct hist_entry *__hists__add_entry(struct hists *self,
},
.ip = al->addr,
.level = al->level,
.count = count,
.period = period,
.parent = sym_parent,
};
int cmp;
Expand All @@ -82,7 +83,8 @@ struct hist_entry *__hists__add_entry(struct hists *self,
cmp = hist_entry__cmp(&entry, he);

if (!cmp) {
he->count += count;
he->period += period;
++he->nr_events;
goto out;
}

Expand All @@ -99,7 +101,7 @@ struct hist_entry *__hists__add_entry(struct hists *self,
rb_insert_color(&he->rb_node, &self->entries);
hists__inc_nr_entries(self, he);
out:
hist_entry__add_cpumode_count(he, al->cpumode, count);
hist_entry__add_cpumode_period(he, al->cpumode, period);
return he;
}

Expand Down Expand Up @@ -160,7 +162,7 @@ static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
cmp = hist_entry__collapse(iter, he);

if (!cmp) {
iter->count += he->count;
iter->period += he->period;
hist_entry__free(he);
return false;
}
Expand Down Expand Up @@ -203,7 +205,7 @@ void hists__collapse_resort(struct hists *self)
}

/*
* reverse the map, sort on count.
* reverse the map, sort on period.
*/

static void __hists__insert_output_entry(struct rb_root *entries,
Expand All @@ -222,7 +224,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
parent = *p;
iter = rb_entry(parent, struct hist_entry, rb_node);

if (he->count > iter->count)
if (he->period > iter->period)
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
Expand Down Expand Up @@ -288,7 +290,7 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
}

static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
int depth, int depth_mask, int count,
int depth, int depth_mask, int period,
u64 total_samples, int hits,
int left_margin)
{
Expand All @@ -301,7 +303,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
ret += fprintf(fp, "|");
else
ret += fprintf(fp, " ");
if (!count && i == depth - 1) {
if (!period && i == depth - 1) {
double percent;

percent = hits * 100.0 / total_samples;
Expand Down Expand Up @@ -516,75 +518,75 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
long displacement, bool color, u64 session_total)
{
struct sort_entry *se;
u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us;
u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
const char *sep = symbol_conf.field_sep;
int ret;

if (symbol_conf.exclude_other && !self->parent)
return 0;

if (pair_hists) {
count = self->pair ? self->pair->count : 0;
period = self->pair ? self->pair->period : 0;
total = pair_hists->stats.total_period;
count_sys = self->pair ? self->pair->count_sys : 0;
count_us = self->pair ? self->pair->count_us : 0;
count_guest_sys = self->pair ? self->pair->count_guest_sys : 0;
count_guest_us = self->pair ? self->pair->count_guest_us : 0;
period_sys = self->pair ? self->pair->period_sys : 0;
period_us = self->pair ? self->pair->period_us : 0;
period_guest_sys = self->pair ? self->pair->period_guest_sys : 0;
period_guest_us = self->pair ? self->pair->period_guest_us : 0;
} else {
count = self->count;
period = self->period;
total = session_total;
count_sys = self->count_sys;
count_us = self->count_us;
count_guest_sys = self->count_guest_sys;
count_guest_us = self->count_guest_us;
period_sys = self->period_sys;
period_us = self->period_us;
period_guest_sys = self->period_guest_sys;
period_guest_us = self->period_guest_us;
}

if (total) {
if (color)
ret = percent_color_snprintf(s, size,
sep ? "%.2f" : " %6.2f%%",
(count * 100.0) / total);
(period * 100.0) / total);
else
ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%",
(count * 100.0) / total);
(period * 100.0) / total);
if (symbol_conf.show_cpu_utilization) {
ret += percent_color_snprintf(s + ret, size - ret,
sep ? "%.2f" : " %6.2f%%",
(count_sys * 100.0) / total);
(period_sys * 100.0) / total);
ret += percent_color_snprintf(s + ret, size - ret,
sep ? "%.2f" : " %6.2f%%",
(count_us * 100.0) / total);
(period_us * 100.0) / total);
if (perf_guest) {
ret += percent_color_snprintf(s + ret,
size - ret,
sep ? "%.2f" : " %6.2f%%",
(count_guest_sys * 100.0) /
(period_guest_sys * 100.0) /
total);
ret += percent_color_snprintf(s + ret,
size - ret,
sep ? "%.2f" : " %6.2f%%",
(count_guest_us * 100.0) /
(period_guest_us * 100.0) /
total);
}
}
} else
ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count);
ret = snprintf(s, size, sep ? "%lld" : "%12lld ", period);

if (symbol_conf.show_nr_samples) {
if (sep)
ret += snprintf(s + ret, size - ret, "%c%lld", *sep, count);
ret += snprintf(s + ret, size - ret, "%c%lld", *sep, period);
else
ret += snprintf(s + ret, size - ret, "%11lld", count);
ret += snprintf(s + ret, size - ret, "%11lld", period);
}

if (pair_hists) {
char bf[32];
double old_percent = 0, new_percent = 0, diff;

if (total > 0)
old_percent = (count * 100.0) / total;
old_percent = (period * 100.0) / total;
if (session_total > 0)
new_percent = (self->count * 100.0) / session_total;
new_percent = (self->period * 100.0) / session_total;

diff = new_percent - old_percent;

Expand Down Expand Up @@ -796,6 +798,7 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso)
struct rb_node *nd;

self->nr_entries = self->stats.total_period = 0;
self->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
self->max_sym_namelen = 0;

for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
Expand All @@ -812,7 +815,8 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso)
h->filtered &= ~(1 << HIST_FILTER__DSO);
if (!h->filtered) {
++self->nr_entries;
self->stats.total_period += h->count;
self->stats.total_period += h->period;
self->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events;
if (h->ms.sym &&
self->max_sym_namelen < h->ms.sym->namelen)
self->max_sym_namelen = h->ms.sym->namelen;
Expand All @@ -825,6 +829,7 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
struct rb_node *nd;

self->nr_entries = self->stats.total_period = 0;
self->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
self->max_sym_namelen = 0;

for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
Expand All @@ -837,7 +842,8 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
h->filtered &= ~(1 << HIST_FILTER__THREAD);
if (!h->filtered) {
++self->nr_entries;
self->stats.total_period += h->count;
self->stats.total_period += h->period;
self->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events;
if (h->ms.sym &&
self->max_sym_namelen < h->ms.sym->namelen)
self->max_sym_namelen = h->ms.sym->namelen;
Expand Down Expand Up @@ -881,7 +887,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
h->sum++;
h->ip[offset]++;

pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", self->ms.sym->start,
pr_debug3("%#Lx %s: period++ [ip: %#Lx, %#Lx] => %Ld\n", self->ms.sym->start,
self->ms.sym->name, ip, ip - self->ms.sym->start, h->ip[offset]);
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/util/hist.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ struct hists {

struct hist_entry *__hists__add_entry(struct hists *self,
struct addr_location *al,
struct symbol *parent, u64 count);
struct symbol *parent, u64 period);
extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists,
Expand Down
8 changes: 5 additions & 3 deletions tools/perf/util/newt.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,16 +680,18 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
struct ui_progress *progress;
struct rb_node *nd;
u64 curr_hist = 0;
char seq[] = ".";
char seq[] = ".", unit;
char str[256];
unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE];

if (self->form) {
newtFormDestroy(self->form);
newtPopWindow();
}

snprintf(str, sizeof(str), "Samples: %Ld ",
hists->stats.total_period);
nr_events = convert_unit(nr_events, &unit);
snprintf(str, sizeof(str), "Events: %lu%c ",
nr_events, unit);
newtDrawRootText(0, 0, str);

newtGetScreenSize(NULL, &rows);
Expand Down
Loading

0 comments on commit c82ee82

Please sign in to comment.