perf hist: Clarify events_stats fields usage
The events_stats.total field is too generic, rename it to .total_period, and also add a comment explaining that it is the sum of all the .period fields in samples, that is needed because we use auto-freq to avoid sampling artifacts. Ditto for events_stats.lost, that is the sum of all lost_event.lost fields, i.e. the number of events the kernel dropped. Looking at the users, builtin-sched.c can make use of these fields and stop doing it again. 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>
This commit is contained in:
Родитель
c8446b9bda
Коммит
cee75ac7ec
|
@ -54,7 +54,7 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
session->hists.stats.total += data.period;
|
session->hists.stats.total_period += data.period;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,14 +138,14 @@ static int add_event_total(struct perf_session *session,
|
||||||
if (!hists)
|
if (!hists)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
hists->stats.total += data->period;
|
hists->stats.total_period += data->period;
|
||||||
/*
|
/*
|
||||||
* FIXME: add_event_total should be moved from here to
|
* FIXME: add_event_total should be moved from here to
|
||||||
* perf_session__process_event so that the proper hist is passed to
|
* perf_session__process_event so that the proper hist is passed to
|
||||||
* the event_op methods.
|
* the event_op methods.
|
||||||
*/
|
*/
|
||||||
hists__inc_nr_events(hists, PERF_RECORD_SAMPLE);
|
hists__inc_nr_events(hists, PERF_RECORD_SAMPLE);
|
||||||
session->hists.stats.total += data->period;
|
session->hists.stats.total_period += data->period;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,10 +322,10 @@ static int __cmd_report(void)
|
||||||
if (rb_first(&session->hists.entries) ==
|
if (rb_first(&session->hists.entries) ==
|
||||||
rb_last(&session->hists.entries))
|
rb_last(&session->hists.entries))
|
||||||
fprintf(stdout, "# Samples: %Ld\n#\n",
|
fprintf(stdout, "# Samples: %Ld\n#\n",
|
||||||
hists->stats.total);
|
hists->stats.total_period);
|
||||||
else
|
else
|
||||||
fprintf(stdout, "# Samples: %Ld %s\n#\n",
|
fprintf(stdout, "# Samples: %Ld %s\n#\n",
|
||||||
hists->stats.total,
|
hists->stats.total_period,
|
||||||
__event_name(hists->type, hists->config));
|
__event_name(hists->type, hists->config));
|
||||||
|
|
||||||
hists__fprintf(hists, NULL, false, stdout);
|
hists__fprintf(hists, NULL, false, stdout);
|
||||||
|
|
|
@ -1641,19 +1641,10 @@ static int process_sample_event(event_t *event, struct perf_session *session)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_lost_event(event_t *event __used,
|
|
||||||
struct perf_session *session __used)
|
|
||||||
{
|
|
||||||
nr_lost_chunks++;
|
|
||||||
nr_lost_events += event->lost.lost;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct perf_event_ops event_ops = {
|
static struct perf_event_ops event_ops = {
|
||||||
.sample = process_sample_event,
|
.sample = process_sample_event,
|
||||||
.comm = event__process_comm,
|
.comm = event__process_comm,
|
||||||
.lost = process_lost_event,
|
.lost = event__process_lost,
|
||||||
.ordered_samples = true,
|
.ordered_samples = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1664,8 +1655,12 @@ static int read_events(void)
|
||||||
if (session == NULL)
|
if (session == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (perf_session__has_traces(session, "record -R"))
|
if (perf_session__has_traces(session, "record -R")) {
|
||||||
err = perf_session__process_events(session, &event_ops);
|
err = perf_session__process_events(session, &event_ops);
|
||||||
|
nr_events = session->hists.stats.nr_events[0];
|
||||||
|
nr_lost_events = session->hists.stats.total_lost;
|
||||||
|
nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST];
|
||||||
|
}
|
||||||
|
|
||||||
perf_session__delete(session);
|
perf_session__delete(session);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -109,7 +109,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
|
||||||
data.time, thread->comm);
|
data.time, thread->comm);
|
||||||
}
|
}
|
||||||
|
|
||||||
session->hists.stats.total += data.period;
|
session->hists.stats.total_period += data.period;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -385,7 +385,7 @@ int event__process_comm(event_t *self, struct perf_session *session)
|
||||||
int event__process_lost(event_t *self, struct perf_session *session)
|
int event__process_lost(event_t *self, struct perf_session *session)
|
||||||
{
|
{
|
||||||
dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost);
|
dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost);
|
||||||
session->hists.stats.lost += self->lost.lost;
|
session->hists.stats.total_lost += self->lost.lost;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,7 +239,7 @@ void hists__output_resort(struct hists *self)
|
||||||
struct hist_entry *n;
|
struct hist_entry *n;
|
||||||
u64 min_callchain_hits;
|
u64 min_callchain_hits;
|
||||||
|
|
||||||
min_callchain_hits = self->stats.total * (callchain_param.min_percent / 100);
|
min_callchain_hits = self->stats.total_period * (callchain_param.min_percent / 100);
|
||||||
|
|
||||||
tmp = RB_ROOT;
|
tmp = RB_ROOT;
|
||||||
next = rb_first(&self->entries);
|
next = rb_first(&self->entries);
|
||||||
|
@ -525,7 +525,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
|
||||||
|
|
||||||
if (pair_hists) {
|
if (pair_hists) {
|
||||||
count = self->pair ? self->pair->count : 0;
|
count = self->pair ? self->pair->count : 0;
|
||||||
total = pair_hists->stats.total;
|
total = pair_hists->stats.total_period;
|
||||||
count_sys = self->pair ? self->pair->count_sys : 0;
|
count_sys = self->pair ? self->pair->count_sys : 0;
|
||||||
count_us = self->pair ? self->pair->count_us : 0;
|
count_us = self->pair ? self->pair->count_us : 0;
|
||||||
count_guest_sys = self->pair ? self->pair->count_guest_sys : 0;
|
count_guest_sys = self->pair ? self->pair->count_guest_sys : 0;
|
||||||
|
@ -769,10 +769,10 @@ print_entries:
|
||||||
++position;
|
++position;
|
||||||
}
|
}
|
||||||
ret += hist_entry__fprintf(h, pair, show_displacement,
|
ret += hist_entry__fprintf(h, pair, show_displacement,
|
||||||
displacement, fp, self->stats.total);
|
displacement, fp, self->stats.total_period);
|
||||||
|
|
||||||
if (symbol_conf.use_callchain)
|
if (symbol_conf.use_callchain)
|
||||||
ret += hist_entry__fprintf_callchain(h, fp, self->stats.total);
|
ret += hist_entry__fprintf_callchain(h, fp, self->stats.total_period);
|
||||||
|
|
||||||
if (h->ms.map == NULL && verbose > 1) {
|
if (h->ms.map == NULL && verbose > 1) {
|
||||||
__map_groups__fprintf_maps(&h->thread->mg,
|
__map_groups__fprintf_maps(&h->thread->mg,
|
||||||
|
@ -795,7 +795,7 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso)
|
||||||
{
|
{
|
||||||
struct rb_node *nd;
|
struct rb_node *nd;
|
||||||
|
|
||||||
self->nr_entries = self->stats.total = 0;
|
self->nr_entries = self->stats.total_period = 0;
|
||||||
self->max_sym_namelen = 0;
|
self->max_sym_namelen = 0;
|
||||||
|
|
||||||
for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
|
for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
|
||||||
|
@ -812,7 +812,7 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso)
|
||||||
h->filtered &= ~(1 << HIST_FILTER__DSO);
|
h->filtered &= ~(1 << HIST_FILTER__DSO);
|
||||||
if (!h->filtered) {
|
if (!h->filtered) {
|
||||||
++self->nr_entries;
|
++self->nr_entries;
|
||||||
self->stats.total += h->count;
|
self->stats.total_period += h->count;
|
||||||
if (h->ms.sym &&
|
if (h->ms.sym &&
|
||||||
self->max_sym_namelen < h->ms.sym->namelen)
|
self->max_sym_namelen < h->ms.sym->namelen)
|
||||||
self->max_sym_namelen = h->ms.sym->namelen;
|
self->max_sym_namelen = h->ms.sym->namelen;
|
||||||
|
@ -824,7 +824,7 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
|
||||||
{
|
{
|
||||||
struct rb_node *nd;
|
struct rb_node *nd;
|
||||||
|
|
||||||
self->nr_entries = self->stats.total = 0;
|
self->nr_entries = self->stats.total_period = 0;
|
||||||
self->max_sym_namelen = 0;
|
self->max_sym_namelen = 0;
|
||||||
|
|
||||||
for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
|
for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
|
||||||
|
@ -837,7 +837,7 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
|
||||||
h->filtered &= ~(1 << HIST_FILTER__THREAD);
|
h->filtered &= ~(1 << HIST_FILTER__THREAD);
|
||||||
if (!h->filtered) {
|
if (!h->filtered) {
|
||||||
++self->nr_entries;
|
++self->nr_entries;
|
||||||
self->stats.total += h->count;
|
self->stats.total_period += h->count;
|
||||||
if (h->ms.sym &&
|
if (h->ms.sym &&
|
||||||
self->max_sym_namelen < h->ms.sym->namelen)
|
self->max_sym_namelen < h->ms.sym->namelen)
|
||||||
self->max_sym_namelen = h->ms.sym->namelen;
|
self->max_sym_namelen = h->ms.sym->namelen;
|
||||||
|
@ -1031,8 +1031,8 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
|
||||||
|
|
||||||
void hists__inc_nr_events(struct hists *self, u32 type)
|
void hists__inc_nr_events(struct hists *self, u32 type)
|
||||||
{
|
{
|
||||||
++self->hists.stats.nr_events[0];
|
++self->stats.nr_events[0];
|
||||||
++self->hists.stats.nr_events[type];
|
++self->stats.nr_events[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
|
size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
|
||||||
|
|
|
@ -37,9 +37,21 @@ struct sym_priv {
|
||||||
struct sym_ext *ext;
|
struct sym_ext *ext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The kernel collects the number of events it couldn't send in a stretch and
|
||||||
|
* when possible sends this number in a PERF_RECORD_LOST event. The number of
|
||||||
|
* such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
|
||||||
|
* total_lost tells exactly how many events the kernel in fact lost, i.e. it is
|
||||||
|
* the sum of all struct lost_event.lost fields reported.
|
||||||
|
*
|
||||||
|
* The total_period is needed because by default auto-freq is used, so
|
||||||
|
* multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
|
||||||
|
* the total number of low level events, it is necessary to to sum all struct
|
||||||
|
* sample_event.period and stash the result in total_period.
|
||||||
|
*/
|
||||||
struct events_stats {
|
struct events_stats {
|
||||||
u64 total;
|
u64 total_period;
|
||||||
u64 lost;
|
u64 total_lost;
|
||||||
u32 nr_events[PERF_RECORD_HEADER_MAX];
|
u32 nr_events[PERF_RECORD_HEADER_MAX];
|
||||||
u32 nr_unknown_events;
|
u32 nr_unknown_events;
|
||||||
};
|
};
|
||||||
|
|
|
@ -689,7 +689,7 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "Samples: %Ld ",
|
snprintf(str, sizeof(str), "Samples: %Ld ",
|
||||||
hists->stats.total);
|
hists->stats.total_period);
|
||||||
newtDrawRootText(0, 0, str);
|
newtDrawRootText(0, 0, str);
|
||||||
|
|
||||||
newtGetScreenSize(NULL, &rows);
|
newtGetScreenSize(NULL, &rows);
|
||||||
|
@ -718,12 +718,12 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
|
||||||
if (h->filtered)
|
if (h->filtered)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
len = hist_entry__append_browser(h, self->tree, hists->stats.total);
|
len = hist_entry__append_browser(h, self->tree, hists->stats.total_period);
|
||||||
if (len > max_len)
|
if (len > max_len)
|
||||||
max_len = len;
|
max_len = len;
|
||||||
if (symbol_conf.use_callchain)
|
if (symbol_conf.use_callchain)
|
||||||
hist_entry__append_callchain_browser(h, self->tree,
|
hist_entry__append_callchain_browser(h, self->tree,
|
||||||
hists->stats.total, idx++);
|
hists->stats.total_period, idx++);
|
||||||
++curr_hist;
|
++curr_hist;
|
||||||
if (curr_hist % 5)
|
if (curr_hist % 5)
|
||||||
ui_progress__update(progress, curr_hist);
|
ui_progress__update(progress, curr_hist);
|
||||||
|
|
|
@ -549,7 +549,7 @@ static int perf_session__process_event(struct perf_session *self,
|
||||||
dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
|
dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
|
||||||
offset + head, event->header.size,
|
offset + head, event->header.size,
|
||||||
event__name[event->header.type]);
|
event__name[event->header.type]);
|
||||||
hists__inc_nr_events(self, event->header.type);
|
hists__inc_nr_events(&self->hists, event->header.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->header.needs_swap && event__swap_ops[event->header.type])
|
if (self->header.needs_swap && event__swap_ops[event->header.type])
|
||||||
|
|
Загрузка…
Ссылка в новой задаче