Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c02c4d2 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo
Browse files

perf hist: Introduce hists class and move lots of methods to it



In cbbc79a5 we introduced support for multiple events by introducing a
new "event_stat_id" struct and then made several perf_session methods
receive a point to it instead of a pointer to perf_session, and kept the
event_stats and hists rb_tree in perf_session.

While working on the new newt based browser, I realised that it would be
better to introduce a new class, "hists" (short for "histograms"),
renaming the "event_stat_id" struct and the perf_session methods that
were really "hists" methods, as they manipulate only struct hists
members, not touching anything in the other perf_session members.

Other optimizations, such as calculating the maximum lenght of a symbol
name present in an hists instance will be possible as we add them,
avoiding a re-traversal just for finding that information.

The rationale for the name "hists" to replace "event_stat_id" is that we
may have multiple sets of hists for the same event_stat id, as, for
instance, the 'perf diff' tool has, so event stat id is not what
characterizes what this struct and the functions that manipulate it do.

Cc: Eric B Munson <ebmunson@us.ibm.com>
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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent d118f8ba
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -96,8 +96,7 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip)
	return 0;
}

static int perf_session__add_hist_entry(struct perf_session *self,
					struct addr_location *al)
static int hists__add_entry(struct hists *self, struct addr_location *al)
{
	struct hist_entry *he;

@@ -112,7 +111,7 @@ static int perf_session__add_hist_entry(struct perf_session *self,
		return 0;
	}

	he = __perf_session__add_hist_entry(&self->hists, al, NULL, 1);
	he = __hists__add_entry(self, al, NULL, 1);
	if (he == NULL)
		return -ENOMEM;

@@ -132,7 +131,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
		return -1;
	}

	if (!al.filtered && perf_session__add_hist_entry(session, &al)) {
	if (!al.filtered && hists__add_entry(&session->hists, &al)) {
		pr_warning("problem incrementing symbol count, "
			   "skipping event\n");
		return -1;
@@ -514,11 +513,11 @@ static void annotate_sym(struct hist_entry *he)
		free_source_line(he, len);
}

static void perf_session__find_annotations(struct perf_session *self)
static void hists__find_annotations(struct hists *self)
{
	struct rb_node *nd;

	for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
	for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
		struct sym_priv *priv;

@@ -570,9 +569,9 @@ static int __cmd_annotate(void)
	if (verbose > 2)
		perf_session__fprintf_dsos(session, stdout);

	perf_session__collapse_resort(&session->hists);
	perf_session__output_resort(&session->hists, session->event_total[0]);
	perf_session__find_annotations(session);
	hists__collapse_resort(&session->hists);
	hists__output_resort(&session->hists);
	hists__find_annotations(&session->hists);
out_delete:
	perf_session__delete(session);

+23 −27
Original line number Diff line number Diff line
@@ -22,10 +22,10 @@ static char diff__default_sort_order[] = "dso,symbol";
static bool  force;
static bool show_displacement;

static int perf_session__add_hist_entry(struct perf_session *self,
static int hists__add_entry(struct hists *self,
			    struct addr_location *al, u64 count)
{
	if (__perf_session__add_hist_entry(&self->hists, al, NULL, count) != NULL)
	if (__hists__add_entry(self, al, NULL, count) != NULL)
		return 0;
	return -ENOMEM;
}
@@ -49,12 +49,12 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi

	event__parse_sample(event, session->sample_type, &data);

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

	session->events_stats.total += data.period;
	session->hists.stats.total += data.period;
	return 0;
}

@@ -87,35 +87,34 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
	rb_insert_color(&he->rb_node, root);
}

static void perf_session__resort_hist_entries(struct perf_session *self)
static void hists__resort_entries(struct hists *self)
{
	unsigned long position = 1;
	struct rb_root tmp = RB_ROOT;
	struct rb_node *next = rb_first(&self->hists);
	struct rb_node *next = rb_first(&self->entries);

	while (next != NULL) {
		struct hist_entry *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, &self->entries);
		n->position = position++;
		perf_session__insert_hist_entry_by_name(&tmp, n);
	}

	self->hists = tmp;
	self->entries = tmp;
}

static void perf_session__set_hist_entries_positions(struct perf_session *self)
static void hists__set_positions(struct hists *self)
{
	perf_session__output_resort(&self->hists, self->events_stats.total);
	perf_session__resort_hist_entries(self);
	hists__output_resort(self);
	hists__resort_entries(self);
}

static struct hist_entry *
perf_session__find_hist_entry(struct perf_session *self,
static struct hist_entry *hists__find_entry(struct hists *self,
					    struct hist_entry *he)
{
	struct rb_node *n = self->hists.rb_node;
	struct rb_node *n = self->entries.rb_node;

	while (n) {
		struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node);
@@ -132,14 +131,13 @@ perf_session__find_hist_entry(struct perf_session *self,
	return NULL;
}

static void perf_session__match_hists(struct perf_session *old_session,
				      struct perf_session *new_session)
static void hists__match(struct hists *older, struct hists *newer)
{
	struct rb_node *nd;

	for (nd = rb_first(&new_session->hists); nd; nd = rb_next(nd)) {
	for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) {
		struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node);
		pos->pair = perf_session__find_hist_entry(old_session, pos);
		pos->pair = hists__find_entry(older, pos);
	}
}

@@ -159,15 +157,13 @@ static int __cmd_diff(void)
			goto out_delete;
	}

	perf_session__output_resort(&session[1]->hists,
				    session[1]->events_stats.total);
	hists__output_resort(&session[1]->hists);
	if (show_displacement)
		perf_session__set_hist_entries_positions(session[0]);
		hists__set_positions(&session[0]->hists);

	perf_session__match_hists(session[0], session[1]);
	perf_session__fprintf_hists(&session[1]->hists, session[0],
				    show_displacement, stdout,
				    session[1]->events_stats.total);
	hists__match(&session[0]->hists, &session[1]->hists);
	hists__fprintf(&session[1]->hists, &session[0]->hists,
		       show_displacement, stdout);
out_delete:
	for (i = 0; i < 2; ++i)
		perf_session__delete(session[i]);
+35 −36
Original line number Diff line number Diff line
@@ -44,16 +44,17 @@ 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)
static struct hists *perf_session__hists_findnew(struct perf_session *self,
						 u64 event_stream, u32 type,
						 u64 config)
{
	struct rb_node **p = &self->stats_by_id.rb_node;
	struct rb_node **p = &self->hists_tree.rb_node;
	struct rb_node *parent = NULL;
	struct event_stat_id *iter, *new;
	struct hists *iter, *new;

	while (*p != NULL) {
		parent = *p;
		iter = rb_entry(parent, struct event_stat_id, rb_node);
		iter = rb_entry(parent, struct hists, rb_node);
		if (iter->config == config)
			return iter;

@@ -64,15 +65,15 @@ static struct event_stat_id *get_stats(struct perf_session *self,
			p = &(*p)->rb_left;
	}

	new = malloc(sizeof(struct event_stat_id));
	new = malloc(sizeof(struct hists));
	if (new == NULL)
		return NULL;
	memset(new, 0, sizeof(struct event_stat_id));
	memset(new, 0, sizeof(struct hists));
	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);
	rb_insert_color(&new->rb_node, &self->hists_tree);
	return new;
}

@@ -84,7 +85,7 @@ static int perf_session__add_hist_entry(struct perf_session *self,
	struct symbol *parent = NULL;
	int err = -ENOMEM;
	struct hist_entry *he;
	struct event_stat_id *stats;
	struct hists *hists;
	struct perf_event_attr *attr;

	if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) {
@@ -96,13 +97,12 @@ static int perf_session__add_hist_entry(struct perf_session *self,

	attr = perf_header__find_attr(data->id, &self->header);
	if (attr)
		stats = get_stats(self, data->id, attr->type, attr->config);
		hists = perf_session__hists_findnew(self, data->id, attr->type, attr->config);
	else
		stats = get_stats(self, data->id, 0, 0);
	if (stats == NULL)
		hists = perf_session__hists_findnew(self, data->id, 0, 0);
	if (hists == NULL)
		goto out_free_syms;
	he = __perf_session__add_hist_entry(&stats->hists, al, parent,
					    data->period);
	he = __hists__add_entry(hists, al, parent, data->period);
	if (he == NULL)
		goto out_free_syms;
	err = 0;
@@ -117,18 +117,19 @@ static int add_event_total(struct perf_session *session,
			   struct sample_data *data,
			   struct perf_event_attr *attr)
{
	struct event_stat_id *stats;
	struct hists *hists;

	if (attr)
		stats = get_stats(session, data->id, attr->type, attr->config);
		hists = perf_session__hists_findnew(session, data->id,
						    attr->type, attr->config);
	else
		stats = get_stats(session, data->id, 0, 0);
		hists = perf_session__hists_findnew(session, data->id, 0, 0);

	if (!stats)
	if (!hists)
		return -ENOMEM;

	stats->stats.total += data->period;
	session->events_stats.total += data->period;
	hists->stats.total += data->period;
	session->hists.stats.total += data->period;
	return 0;
}

@@ -292,35 +293,33 @@ static int __cmd_report(void)
	if (verbose > 2)
		perf_session__fprintf_dsos(session, stdout);

	next = rb_first(&session->stats_by_id);
	next = rb_first(&session->hists_tree);
	while (next) {
		struct event_stat_id *stats;
		struct hists *hists;
		u64 nr_hists;

		stats = rb_entry(next, struct event_stat_id, rb_node);
		perf_session__collapse_resort(&stats->hists);
		nr_hists = perf_session__output_resort(&stats->hists,
						       stats->stats.total);
		hists = rb_entry(next, struct hists, rb_node);
		hists__collapse_resort(hists);
		nr_hists = hists__output_resort(hists);
		if (use_browser)
			perf_session__browse_hists(&stats->hists, nr_hists,
						   stats->stats.total, help,
			perf_session__browse_hists(&hists->entries, nr_hists,
						   hists->stats.total, help,
						   input_name);
		else {
			if (rb_first(&session->stats_by_id) ==
			    rb_last(&session->stats_by_id))
			if (rb_first(&session->hists.entries) ==
			    rb_last(&session->hists.entries))
				fprintf(stdout, "# Samples: %Ld\n#\n",
					stats->stats.total);
					hists->stats.total);
			else
				fprintf(stdout, "# Samples: %Ld %s\n#\n",
					stats->stats.total,
					__event_name(stats->type, stats->config));
					hists->stats.total,
					__event_name(hists->type, hists->config));

			perf_session__fprintf_hists(&stats->hists, NULL, false, stdout,
					    stats->stats.total);
			hists__fprintf(hists, NULL, false, stdout);
			fprintf(stdout, "\n\n");
		}

		next = rb_next(&stats->rb_node);
		next = rb_next(&hists->rb_node);
	}

	if (!use_browser && sort_order == default_sort_order &&
+1 −1
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
					     data.time, thread->comm);
	}

	session->events_stats.total += data.period;
	session->hists.stats.total += data.period;
	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -368,7 +368,7 @@ int event__process_comm(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);
	session->events_stats.lost += self->lost.lost;
	session->hists.stats.lost += self->lost.lost;
	return 0;
}

Loading