Signed-off-by: Eric B Munson <ebmu...@us.ibm.com>
---
tools/perf/builtin-record.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 771533c..35e4605 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -242,7 +242,8 @@ static void create_counter(int counter, int cpu, pid_t pid)
PERF_FORMAT_TOTAL_TIME_RUNNING |
PERF_FORMAT_ID;
- attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+ attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
+ PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID;
if (freq) {
attr->sample_type |= PERF_SAMPLE_PERIOD;
--
1.6.3.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Signed-off-by: Eric B Munson <ebmu...@us.ibm.com>
---
tools/perf/util/event.h | 9 +++++++++
tools/perf/util/session.c | 1 +
tools/perf/util/session.h | 1 +
3 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 50a7132..a33b949 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -99,6 +99,15 @@ struct events_stats {
u64 lost;
};
+struct event_stat_id {
+ struct rb_node rb_node;
+ struct rb_root hists;
+ struct events_stats stats;
+ u64 config;
+ u64 event_stream;
+ u32 type;
+};
+
void event__print_totals(void);
struct perf_session;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0de7258..eed1cb8 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -70,6 +70,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
memcpy(self->filename, filename, len);
self->threads = RB_ROOT;
+ self->stats_by_id = RB_ROOT;
self->last_match = NULL;
self->mmap_window = 32;
self->cwd = NULL;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 31950fc..5c33417 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -20,6 +20,7 @@ struct perf_session {
struct thread *last_match;
struct map *vmlinux_maps[MAP__NR_TYPES];
struct events_stats events_stats;
+ struct rb_root stats_by_id;
unsigned long event_total[PERF_RECORD_MAX];
unsigned long unknown_events;
struct rb_root hists;
Signed-off-by: Eric B Munson <ebmu...@us.ibm.com>
---
tools/perf/builtin-report.c | 105 +++++++++++++++++++++++++++++++++++++-----
1 files changed, 92 insertions(+), 13 deletions(-)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index cd16e6a..dcfb565 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -45,29 +45,71 @@ static char *pretty_printing_style = default_pretty_printing_style;
static char callchain_default_opt[] = "fractal,0.5";
+static struct event_stat_id *get_stats(struct perf_session *self, u64 event_stream,
+ u32 type, u64 config)
+{
+ struct rb_node **p = &self->stats_by_id.rb_node;
+ struct rb_node *parent = NULL;
+ struct event_stat_id *iter, *new;
+
+ while (*p != NULL) {
+ parent = *p;
+ iter = rb_entry(parent, struct event_stat_id, rb_node);
+ if (iter->config == config) {
+ return iter;
+ }
+
+ if (config > iter->config)
+ p = &(*p)->rb_right;
+ else
+ p = &(*p)->rb_left;
+ }
+
+ new = malloc(sizeof(struct event_stat_id));
+ if (new == NULL)
+ return NULL;
+ memset(new, 0, sizeof(struct event_stat_id));
+ new->event_stream = event_stream;
+ new->config = config;
+ new->type = type;
+ rb_link_node(&new->rb_node, parent, p);
+ rb_insert_color(&new->rb_node, &self->stats_by_id);
+ return new;
+}
+
static int perf_session__add_hist_entry(struct perf_session *self,
struct addr_location *al,
- struct ip_callchain *chain, u64 count)
+ struct sample_data *data)
{
struct symbol **syms = NULL, *parent = NULL;
bool hit;
struct hist_entry *he;
+ struct event_stat_id *stats;
+ struct perf_event_attr *attr;
- if ((sort__has_parent || symbol_conf.use_callchain) && chain)
+ if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain)
syms = perf_session__resolve_callchain(self, al->thread,
- chain, &parent);
- he = __perf_session__add_hist_entry(&self->hists, al, parent,
- count, &hit);
+ data->callchain, &parent);
+
+ attr = perf_header__find_attr(data->id, &self->header);
+ if (attr)
+ stats = get_stats(self, data->id, attr->type, attr->config);
+ else
+ stats = get_stats(self, data->id, 0, 0);
+ if (stats == NULL)
+ return -ENOMEM;
+ he = __perf_session__add_hist_entry(&stats->hists, al, parent,
+ data->period, &hit);
if (he == NULL)
return -ENOMEM;
if (hit)
- he->count += count;
+ he->count += data->period;
if (symbol_conf.use_callchain) {
if (!hit)
callchain_init(&he->callchain);
- append_chain(&he->callchain, chain, syms);
+ append_chain(&he->callchain, data->callchain, syms);
free(syms);
}
@@ -87,10 +129,29 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)
return 0;
}
+static int add_event_total(struct perf_session *session, struct sample_data *data,
+ struct perf_event_attr *attr)
+{
+ struct event_stat_id *stats;
+
+ if (attr)
+ stats = get_stats(session, data->id, attr->type, attr->config);
+ else
+ stats = get_stats(session, data->id, 0, 0);
+
+ if (!stats)
+ return -ENOMEM;
+
+ stats->stats.total += data->period;
+ session->events_stats.total += data->period;
+ return 0;
+}
+
static int process_sample_event(event_t *event, struct perf_session *session)
{
struct sample_data data = { .period = 1, };
struct addr_location al;
+ struct perf_event_attr *attr;
event__parse_sample(event, session->sample_type, &data);
@@ -124,12 +185,18 @@ static int process_sample_event(event_t *event, struct perf_session *session)
if (al.filtered || (hide_unresolved && al.sym == NULL))
return 0;
- if (perf_session__add_hist_entry(session, &al, data.callchain, data.period)) {
+ if (perf_session__add_hist_entry(session, &al, &data)) {
pr_debug("problem incrementing symbol count, skipping event\n");
return -1;
}
- session->events_stats.total += data.period;
+ attr = perf_header__find_attr(data.id, &session->header);
+
+ if (add_event_total(session, &data, attr)) {
+ pr_debug("problem adding event count\n");
+ return -1;
+ }
+
return 0;
}
@@ -198,6 +265,7 @@ static int __cmd_report(void)
{
int ret = -EINVAL;
struct perf_session *session;
+ struct rb_node *next;
session = perf_session__new(input_name, O_RDONLY, force);
if (session == NULL)
@@ -225,10 +293,21 @@ static int __cmd_report(void)
if (verbose > 2)
dsos__fprintf(stdout);
- perf_session__collapse_resort(session);
- perf_session__output_resort(session, session->events_stats.total);
- fprintf(stdout, "# Samples: %Ld\n#\n", session->events_stats.total);
- perf_session__fprintf_hists(session, NULL, false, stdout);
+ next = rb_first(&session->stats_by_id);
+ while (next) {
+ struct event_stat_id *stats = rb_entry(next,
+ struct event_stat_id,
+ rb_node);
+ perf_session__collapse_resort(&stats->hists);
+ perf_session__output_resort(&stats->hists, stats->stats.total);
+ fprintf(stdout, "# Samples: %Ld %s\n#\n", stats->stats.total,
+ __event_name(stats->type, stats->config));
+ perf_session__fprintf_hists(&stats->hists, NULL, false, stdout,
+ stats->stats.total);
+ fprintf(stdout, "\n\n");
+ next = rb_next(&stats->rb_node);
+ }
+
if (sort_order == default_sort_order &&
parent_pattern == default_parent_pattern)
fprintf(stdout, "#\n# (For a higher level overview, try: perf report --sort comm,dso)\n#\n");
Signed-off-by: Eric B Munson <ebmu...@us.ibm.com>
---
tools/perf/builtin-annotate.c | 2 +-
tools/perf/builtin-diff.c | 3 ++-
tools/perf/builtin-report.c | 3 ++-
tools/perf/util/hist.c | 6 +++---
tools/perf/util/hist.h | 3 ++-
5 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 5ec5de9..4b734c7 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -116,7 +116,7 @@ static int perf_session__add_hist_entry(struct perf_session *self,
return 0;
}
- he = __perf_session__add_hist_entry(self, al, NULL, count, &hit);
+ he = __perf_session__add_hist_entry(&self->hists, al, NULL, count, &hit);
if (he == NULL)
return -ENOMEM;
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 18b3f50..20df735 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -26,7 +26,8 @@ static int perf_session__add_hist_entry(struct perf_session *self,
struct addr_location *al, u64 count)
{
bool hit;
- struct hist_entry *he = __perf_session__add_hist_entry(self, al, NULL,
+ struct hist_entry *he = __perf_session__add_hist_entry(&self->hists,
+ al, NULL,
count, &hit);
if (he == NULL)
return -ENOMEM;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index cfc655d..cd16e6a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -56,7 +56,8 @@ static int perf_session__add_hist_entry(struct perf_session *self,
if ((sort__has_parent || symbol_conf.use_callchain) && chain)
syms = perf_session__resolve_callchain(self, al->thread,
chain, &parent);
- he = __perf_session__add_hist_entry(self, al, parent, count, &hit);
+ he = __perf_session__add_hist_entry(&self->hists, al, parent,
+ count, &hit);
if (he == NULL)
return -ENOMEM;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index e8daf5c..55dd911 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -12,12 +12,12 @@ struct callchain_param callchain_param = {
* histogram, sorted on item, collects counts
*/
-struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
+struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
struct addr_location *al,
struct symbol *sym_parent,
u64 count, bool *hit)
{
- struct rb_node **p = &self->hists.rb_node;
+ struct rb_node **p = &hists->rb_node;
struct rb_node *parent = NULL;
struct hist_entry *he;
struct hist_entry entry = {
@@ -53,7 +53,7 @@ struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
return NULL;
*he = entry;
rb_link_node(&he->rb_node, parent, p);
- rb_insert_color(&he->rb_node, &self->hists);
+ rb_insert_color(&he->rb_node, hists);
*hit = false;
return he;
}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index e5f99b2..7b48590 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -10,8 +10,9 @@ struct perf_session;
struct hist_entry;
struct addr_location;
struct symbol;
+struct rb_root;
-struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
+struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists,
struct addr_location *al,
struct symbol *parent,
u64 count, bool *hit);
Signed-off-by: Eric B Munson <ebmu...@us.ibm.com>
---
tools/perf/builtin-annotate.c | 4 ++--
tools/perf/builtin-diff.c | 9 +++++----
tools/perf/util/hist.c | 39 ++++++++++++++++++++-------------------
tools/perf/util/hist.h | 9 +++++----
4 files changed, 32 insertions(+), 29 deletions(-)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 4b734c7..6ad7148 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -564,8 +564,8 @@ static int __cmd_annotate(void)
if (verbose > 2)
dsos__fprintf(stdout);
- perf_session__collapse_resort(session);
- perf_session__output_resort(session, session->event_total[0]);
+ perf_session__collapse_resort(&session->hists);
+ perf_session__output_resort(&session->hists, session->event_total[0]);
perf_session__find_annotations(session);
out_delete:
perf_session__delete(session);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 20df735..d2781fb 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -115,7 +115,7 @@ static void perf_session__resort_hist_entries(struct perf_session *self)
static void perf_session__set_hist_entries_positions(struct perf_session *self)
{
- perf_session__output_resort(self, self->events_stats.total);
+ perf_session__output_resort(&self->hists, self->events_stats.total);
perf_session__resort_hist_entries(self);
}
@@ -167,13 +167,14 @@ static int __cmd_diff(void)
goto out_delete;
}
- perf_session__output_resort(session[1], session[1]->events_stats.total);
+ perf_session__output_resort(&(session[1]->hists), session[1]->events_stats.total);
if (show_displacement)
perf_session__set_hist_entries_positions(session[0]);
perf_session__match_hists(session[0], session[1]);
- perf_session__fprintf_hists(session[1], session[0],
- show_displacement, stdout);
+ perf_session__fprintf_hists(&(session[1]->hists), session[0],
+ show_displacement, stdout,
+ session[1]->events_stats.total);
out_delete:
for (i = 0; i < 2; ++i)
perf_session__delete(session[i]);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 55dd911..73ebb6f 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -130,7 +130,7 @@ static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
rb_insert_color(&he->rb_node, root);
}
-void perf_session__collapse_resort(struct perf_session *self)
+void perf_session__collapse_resort(struct rb_root *hists)
{
struct rb_root tmp;
struct rb_node *next;
@@ -140,17 +140,17 @@ void perf_session__collapse_resort(struct perf_session *self)
return;
tmp = RB_ROOT;
- next = rb_first(&self->hists);
+ next = rb_first(hists);
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
next = rb_next(&n->rb_node);
- rb_erase(&n->rb_node, &self->hists);
+ rb_erase(&n->rb_node, hists);
collapse__insert_entry(&tmp, n);
}
- self->hists = tmp;
+ *hists = tmp;
}
/*
@@ -183,7 +183,7 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root,
rb_insert_color(&he->rb_node, root);
}
-void perf_session__output_resort(struct perf_session *self, u64 total_samples)
+void perf_session__output_resort(struct rb_root *hists, u64 total_samples)
{
struct rb_root tmp;
struct rb_node *next;
@@ -194,18 +194,18 @@ void perf_session__output_resort(struct perf_session *self, u64 total_samples)
total_samples * (callchain_param.min_percent / 100);
tmp = RB_ROOT;
- next = rb_first(&self->hists);
+ next = rb_first(hists);
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
next = rb_next(&n->rb_node);
- rb_erase(&n->rb_node, &self->hists);
+ rb_erase(&n->rb_node, hists);
perf_session__insert_output_hist_entry(&tmp, n,
min_callchain_hits);
}
- self->hists = tmp;
+ *hists = tmp;
}
static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
@@ -456,10 +456,10 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
}
static size_t hist_entry__fprintf(struct hist_entry *self,
- struct perf_session *session,
struct perf_session *pair_session,
bool show_displacement,
- long displacement, FILE *fp)
+ long displacement, FILE *fp,
+ u64 session_total)
{
struct sort_entry *se;
u64 count, total;
@@ -474,7 +474,7 @@ static size_t hist_entry__fprintf(struct hist_entry *self,
total = pair_session->events_stats.total;
} else {
count = self->count;
- total = session->events_stats.total;
+ total = session_total;
}
if (total)
@@ -496,8 +496,8 @@ static size_t hist_entry__fprintf(struct hist_entry *self,
if (total > 0)
old_percent = (count * 100.0) / total;
- if (session->events_stats.total > 0)
- new_percent = (self->count * 100.0) / session->events_stats.total;
+ if (session_total > 0)
+ new_percent = (self->count * 100.0) / session_total;
diff = new_percent - old_percent;
@@ -544,16 +544,17 @@ static size_t hist_entry__fprintf(struct hist_entry *self,
left_margin -= thread__comm_len(self->thread);
}
- hist_entry_callchain__fprintf(fp, self, session->events_stats.total,
+ hist_entry_callchain__fprintf(fp, self, session_total,
left_margin);
}
return ret;
}
-size_t perf_session__fprintf_hists(struct perf_session *self,
+size_t perf_session__fprintf_hists(struct rb_root *hists,
struct perf_session *pair,
- bool show_displacement, FILE *fp)
+ bool show_displacement, FILE *fp,
+ u64 session_total)
{
struct sort_entry *se;
struct rb_node *nd;
@@ -641,7 +642,7 @@ size_t perf_session__fprintf_hists(struct perf_session *self,
fprintf(fp, "\n#\n");
print_entries:
- for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
+ for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
if (show_displacement) {
@@ -652,8 +653,8 @@ print_entries:
displacement = 0;
++position;
}
- ret += hist_entry__fprintf(h, self, pair, show_displacement,
- displacement, fp);
+ ret += hist_entry__fprintf(h, pair, show_displacement,
+ displacement, fp, session_total);
}
free(rem_sq_bracket);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 7b48590..16f360c 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -20,9 +20,10 @@ extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
void hist_entry__free(struct hist_entry *);
-void perf_session__output_resort(struct perf_session *self, u64 total_samples);
-void perf_session__collapse_resort(struct perf_session *self);
-size_t perf_session__fprintf_hists(struct perf_session *self,
+void perf_session__output_resort(struct rb_root *hists, u64 total_samples);
+void perf_session__collapse_resort(struct rb_root *hists);
+size_t perf_session__fprintf_hists(struct rb_root *hists,
struct perf_session *pair,
- bool show_displacement, FILE *fp);
+ bool show_displacement, FILE *fp,
+ u64 session_total);
#endif /* __PERF_HIST_H */
can we make this conditional on there being more than one event, that
saves a little space/time when recording
> On Tue, 2010-03-02 at 14:42 +0000, Eric B Munson wrote:
> > Currently perf record does not write the ID or the STREAM_ID to disk
> > for events. This doesn't allow report to tell if an event stream contains
> > one or more types of events. This patch adds these two entries to the list
> > of data that record will write to disk.
> >
> > Signed-off-by: Eric B Munson <ebmu...@us.ibm.com>
> > ---
> > tools/perf/builtin-record.c | 3 ++-
> > 1 files changed, 2 insertions(+), 1 deletions(-)
> >
> > diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> > index 771533c..35e4605 100644
> > --- a/tools/perf/builtin-record.c
> > +++ b/tools/perf/builtin-record.c
> > @@ -242,7 +242,8 @@ static void create_counter(int counter, int cpu, pid_t pid)
> > PERF_FORMAT_TOTAL_TIME_RUNNING |
> > PERF_FORMAT_ID;
> >
> > - attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
> > + attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
> > + PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID;
> >
> > if (freq) {
> > attr->sample_type |= PERF_SAMPLE_PERIOD;
>
> can we make this conditional on there being more than one event, that
> saves a little space/time when recording
>
Yeah, I will add that in the next version.
--
Eric B Munson
IBM Linux Technology Center
ebmu...@us.ibm.com
> On Tue, 2010-03-02 at 14:42 +0000, Eric B Munson wrote:
> > Currently perf record does not write the ID or the STREAM_ID to disk
> > for events. This doesn't allow report to tell if an event stream contains
> > one or more types of events. This patch adds these two entries to the list
> > of data that record will write to disk.
> >
> > Signed-off-by: Eric B Munson <ebmu...@us.ibm.com>
> > ---
> > tools/perf/builtin-record.c | 3 ++-
> > 1 files changed, 2 insertions(+), 1 deletions(-)
> >
> > diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> > index 771533c..35e4605 100644
> > --- a/tools/perf/builtin-record.c
> > +++ b/tools/perf/builtin-record.c
> > @@ -242,7 +242,8 @@ static void create_counter(int counter, int cpu, pid_t pid)
> > PERF_FORMAT_TOTAL_TIME_RUNNING |
> > PERF_FORMAT_ID;
> >
> > - attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
> > + attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
> > + PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID;
> >
> > if (freq) {
> > attr->sample_type |= PERF_SAMPLE_PERIOD;
>
> can we make this conditional on there being more than one event, that
> saves a little space/time when recording
>
The downside to this is report cannot print the name of the event being monitored
if we do not record the sample and stream id. This is as report behaves currently
and if that is okay then I will put out V2 with that included today.
Well, if there's only one event, its clear what name to use, and if
there's more than one event, we will include the ID.
BTW, I think you can do without the STREAM_ID, since that is only used
to account throttled state iirc, and we don't actually do that.