From: Don Zickus <dzickus@redhat.com>
To: acme@kernel.org, namhyung@kernel.org, jolsa@redhat.com
Cc: eranian@google.com, Andi Kleen <andi@firstfloor.org>,
LKML <linux-kernel@vger.kernel.org>,
Don Zickus <dzickus@redhat.com>
Subject: [RFC 2/5] perf: Use macros to walk hist entries
Date: Thu, 10 Apr 2014 16:10:58 -0400 [thread overview]
Message-ID: <1397160661-33395-3-git-send-email-dzickus@redhat.com> (raw)
In-Reply-To: <1397160661-33395-1-git-send-email-dzickus@redhat.com>
There is code copied everywhere to walk the hist entry list. Turn this
into a macro to minimize errors later. Also useful for converting to group
hist entries later.
New macros are:
hist__for_each_entry_in
hist__for_each_entry_in_safe
hist__for_each_entry_out
Most code that looks like this:
if (sort__neeed_collapse)
root = &hists->entries_collapsed;
else
root = hists->entries_in;
next = rb_first(root);
while (next != NULL) {
struct hist_entry *he = rb_entry(....)
next = rb_next(&he->rb_node_in);
and turns it into
hist__for_each_entry_in(he, hists) {
One advantage (besides smaller written code), is one doesn't have to remember
which struct fields are for input data or output data (entries_in vs. entries)
and their correspoding rb_node hook (rb_node_in vs. rb_node).
Most obvious places have been converted, some unusual cases stayed unchanged.
Should be a mostly mechanical change and nothing should change from a technical
perspective.
Signed-off-by: Don Zickus <dzickus@redhat.com>
---
tools/perf/builtin-diff.c | 48 ++++++----------------------------
tools/perf/builtin-top.c | 6 +----
tools/perf/tests/hists_link.c | 51 +++++-------------------------------
tools/perf/ui/browsers/hists.c | 5 ++--
tools/perf/ui/gtk/hists.c | 5 ++--
tools/perf/ui/stdio/hist.c | 5 ++--
tools/perf/util/hist.c | 34 +++---------------------
tools/perf/util/sort.h | 59 ++++++++++++++++++++++++++++++++++++++++++
8 files changed, 83 insertions(+), 130 deletions(-)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 2e4857d..837d0e2 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -400,21 +400,11 @@ get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
static void hists__baseline_only(struct hists *hists)
{
- struct rb_root *root;
- struct rb_node *next;
+ struct hist_entry *he, *next;
- if (sort__need_collapse)
- root = &hists->entries_collapsed;
- else
- root = hists->entries_in;
-
- next = rb_first(root);
- while (next != NULL) {
- struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in);
-
- next = rb_next(&he->rb_node_in);
+ hist__for_each_entry_in_safe(he, next, hists) {
if (!hist_entry__next_pair(he)) {
- rb_erase(&he->rb_node_in, root);
+ rb_erase(&he->rb_node_in, hists__get_root(hists));
hist_entry__free(he);
}
}
@@ -422,20 +412,10 @@ static void hists__baseline_only(struct hists *hists)
static void hists__precompute(struct hists *hists)
{
- struct rb_root *root;
- struct rb_node *next;
-
- if (sort__need_collapse)
- root = &hists->entries_collapsed;
- else
- root = hists->entries_in;
-
- next = rb_first(root);
- while (next != NULL) {
- struct hist_entry *he, *pair;
+ struct hist_entry *he;
- he = rb_entry(next, struct hist_entry, rb_node_in);
- next = rb_next(&he->rb_node_in);
+ hist__for_each_entry_in(he, hists) {
+ struct hist_entry *pair;
pair = get_pair_data(he, &data__files[sort_compute]);
if (!pair)
@@ -553,27 +533,15 @@ static void insert_hist_entry_by_compute(struct rb_root *root,
static void hists__compute_resort(struct hists *hists)
{
- struct rb_root *root;
- struct rb_node *next;
-
- if (sort__need_collapse)
- root = &hists->entries_collapsed;
- else
- root = hists->entries_in;
+ struct hist_entry *he;
hists->entries = RB_ROOT;
- next = rb_first(root);
hists->nr_entries = 0;
hists->stats.total_period = 0;
hists__reset_col_len(hists);
- while (next != NULL) {
- struct hist_entry *he;
-
- he = rb_entry(next, struct hist_entry, rb_node_in);
- next = rb_next(&he->rb_node_in);
-
+ hist__for_each_entry_in(he, hists) {
insert_hist_entry_by_compute(&hists->entries, he, compute);
hists__inc_nr_entries(hists, he);
}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e58b124..427f2e2 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -338,7 +338,6 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
{
char *buf = malloc(0), *p;
struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
- struct rb_node *next;
size_t dummy = 0;
/* zero counters of active symbol */
@@ -355,14 +354,11 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
if (p)
*p = 0;
- next = rb_first(&top->sym_evsel->hists.entries);
- while (next) {
- n = rb_entry(next, struct hist_entry, rb_node);
+ hist__for_each_entry_out(n, (&top->sym_evsel->hists)) {
if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
found = n;
break;
}
- next = rb_next(&n->rb_node);
}
if (!found) {
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index bd851c6..a0def6b 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -280,23 +280,9 @@ static int find_sample(struct sample *samples, size_t nr_samples,
static int __validate_match(struct hists *hists)
{
size_t count = 0;
- struct rb_root *root;
- struct rb_node *node;
-
- /*
- * Only entries from fake_common_samples should have a pair.
- */
- if (sort__need_collapse)
- root = &hists->entries_collapsed;
- else
- root = hists->entries_in;
-
- node = rb_first(root);
- while (node) {
- struct hist_entry *he;
-
- he = rb_entry(node, struct hist_entry, rb_node_in);
+ struct hist_entry *he;
+ hist__for_each_entry_in(he, hists) {
if (hist_entry__has_pairs(he)) {
if (find_sample(fake_common_samples,
ARRAY_SIZE(fake_common_samples),
@@ -307,8 +293,6 @@ static int __validate_match(struct hists *hists)
return -1;
}
}
-
- node = rb_next(node);
}
if (count != ARRAY_SIZE(fake_common_samples)) {
@@ -330,25 +314,15 @@ static int __validate_link(struct hists *hists, int idx)
size_t count = 0;
size_t count_pair = 0;
size_t count_dummy = 0;
- struct rb_root *root;
- struct rb_node *node;
+ struct hist_entry *he;
/*
* Leader hists (idx = 0) will have dummy entries from other,
* and some entries will have no pair. However every entry
* in other hists should have (dummy) pair.
*/
- if (sort__need_collapse)
- root = &hists->entries_collapsed;
- else
- root = hists->entries_in;
-
- node = rb_first(root);
- while (node) {
- struct hist_entry *he;
-
- he = rb_entry(node, struct hist_entry, rb_node_in);
+ hist__for_each_entry_in(he, hists) {
if (hist_entry__has_pairs(he)) {
if (!find_sample(fake_common_samples,
ARRAY_SIZE(fake_common_samples),
@@ -365,7 +339,6 @@ static int __validate_link(struct hists *hists, int idx)
}
count++;
- node = rb_next(node);
}
/*
@@ -406,27 +379,15 @@ static int validate_link(struct hists *leader, struct hists *other)
static void print_hists(struct hists *hists)
{
int i = 0;
- struct rb_root *root;
- struct rb_node *node;
-
- if (sort__need_collapse)
- root = &hists->entries_collapsed;
- else
- root = hists->entries_in;
+ struct hist_entry *he;
pr_info("----- %s --------\n", __func__);
- node = rb_first(root);
- while (node) {
- struct hist_entry *he;
-
- he = rb_entry(node, struct hist_entry, rb_node_in);
-
+ hist__for_each_entry_in(he, hists) {
pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n",
i, thread__comm_str(he->thread), he->ms.map->dso->short_name,
he->ms.sym->name, he->stat.period);
i++;
- node = rb_next(node);
}
}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 7ec871a..f2693f3 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -282,12 +282,11 @@ static void hist_entry__set_folding(struct hist_entry *he, bool unfold)
static void hists__set_folding(struct hists *hists, bool unfold)
{
- struct rb_node *nd;
+ struct hist_entry *he;
hists->nr_entries = 0;
- for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
- struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
+ hist__for_each_entry_out(he, hists) {
hist_entry__set_folding(he, unfold);
hists->nr_entries += 1 + he->nr_rows;
}
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index e395ef9..3df6c00a 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -155,12 +155,12 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
GtkCellRenderer *renderer;
struct sort_entry *se;
GtkTreeStore *store;
- struct rb_node *nd;
GtkWidget *view;
int col_idx;
int sym_col = -1;
int nr_cols;
char s[512];
+ struct hist_entry *h;
struct perf_hpp hpp = {
.buf = s,
@@ -225,8 +225,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
g_object_unref(GTK_TREE_MODEL(store));
- for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
- struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+ hist__for_each_entry_out(h, hists) {
GtkTreeIter iter;
float percent = h->stat.period * 100.0 /
hists->stats.total_period;
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index d59893e..96defa8 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -369,7 +369,6 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
{
struct perf_hpp_fmt *fmt;
struct sort_entry *se;
- struct rb_node *nd;
size_t ret = 0;
unsigned int width;
const char *sep = symbol_conf.field_sep;
@@ -383,6 +382,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
bool first = true;
size_t linesz;
char *line = NULL;
+ struct hist_entry *h;
init_rem_hits();
@@ -478,8 +478,7 @@ print_entries:
goto out;
}
- for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
- struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+ hist__for_each_entry_out(h, hists) {
float percent = h->stat.period * 100.0 /
hists->stats.total_period;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 57545b3..68eec0f 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -672,29 +672,18 @@ static void __hists__insert_output_entry(struct rb_root *entries,
void hists__output_resort(struct hists *hists)
{
- struct rb_root *root;
- struct rb_node *next;
struct hist_entry *n;
u64 min_callchain_hits;
min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
- if (sort__need_collapse)
- root = &hists->entries_collapsed;
- else
- root = hists->entries_in;
-
- next = rb_first(root);
hists->entries = RB_ROOT;
hists->nr_entries = 0;
hists->stats.total_period = 0;
hists__reset_col_len(hists);
- while (next) {
- n = rb_entry(next, struct hist_entry, rb_node_in);
- next = rb_next(&n->rb_node_in);
-
+ hist__for_each_entry_in(n, hists) {
__hists__insert_output_entry(&hists->entries, n, min_callchain_hits);
hists__inc_nr_entries(hists, n);
}
@@ -897,17 +886,9 @@ static struct hist_entry *hists__find_entry(struct hists *hists,
*/
void hists__match(struct hists *leader, struct hists *other)
{
- struct rb_root *root;
- struct rb_node *nd;
struct hist_entry *pos, *pair;
- if (sort__need_collapse)
- root = &leader->entries_collapsed;
- else
- root = leader->entries_in;
-
- for (nd = rb_first(root); nd; nd = rb_next(nd)) {
- pos = rb_entry(nd, struct hist_entry, rb_node_in);
+ hist__for_each_entry_in(pos, leader) {
pair = hists__find_entry(other, pos);
if (pair)
@@ -922,18 +903,9 @@ void hists__match(struct hists *leader, struct hists *other)
*/
int hists__link(struct hists *leader, struct hists *other)
{
- struct rb_root *root;
- struct rb_node *nd;
struct hist_entry *pos, *pair;
- if (sort__need_collapse)
- root = &other->entries_collapsed;
- else
- root = other->entries_in;
-
- for (nd = rb_first(root); nd; nd = rb_next(nd)) {
- pos = rb_entry(nd, struct hist_entry, rb_node_in);
-
+ hist__for_each_entry_in(pos, other) {
if (!hist_entry__has_pairs(pos)) {
pair = hists__add_dummy_entry(leader, pos);
if (pair == NULL)
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 43e5ff4..a089986 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -22,6 +22,7 @@
#include "parse-events.h"
#include "thread.h"
+#include "hist.h"
extern regex_t parent_regex;
extern const char *sort_order;
@@ -129,6 +130,64 @@ static inline void hist_entry__add_pair(struct hist_entry *pair,
list_add_tail(&pair->pairs.node, &he->pairs.head);
}
+static inline struct rb_root *hists__get_root(struct hists *hists)
+{
+ if (sort__need_collapse)
+ return &hists->entries_collapsed;
+ else
+ return hists->entries_in;
+}
+
+
+/**
+ * __hist__for_each_entry - iterate thru all the entries in hist
+ * @entry: struct hist_entry to use as a loop cursor
+ * @root: struct rb_root that points to the top of an rbtree
+ * @field: the name of the rb_node within the struct
+ */
+#define __hist__for_each_entry(entry, root, field) \
+ for (entry = rb_entry_safe(rb_first(root), typeof(*entry), field); \
+ entry; \
+ entry = rb_entry_safe(rb_next(&entry->field), typeof(*entry), field))
+
+/**
+ * __hist__for_each_entry_safe - iterate thru all the entries in hist, safe against removal of entry
+ * @entry: struct hist_entry to use as a loop cursor
+ * @next: struct hist_entry to use as temporary storage
+ * @root: struct rb_root that points to the top of an rbtree
+ * @field: the name of the rb_node within the struct
+ */
+#define __hist__for_each_entry_safe(entry, next, root, field) \
+ for (entry = rb_entry_safe(rb_first(root), typeof(*entry), field); \
+ entry && ({ next = rb_entry_safe(rb_next(&entry->field), \
+ typeof(*entry), field); 1; }); \
+ entry = next)
+
+/**
+ * hist__for_each_entry_in - iterate thru all the input entries in hist
+ * @entry: struct hist_entry to use as a loop cursor
+ * @hists: struct hists entry that points to an rb_root tree
+ */
+#define hist__for_each_entry_in(entry, hists) \
+ __hist__for_each_entry(entry, hists__get_root(hists), rb_node_in)
+
+/**
+ * hist__for_each_entry_in_safe - iterate thru all the input entries in hist, safe against removal of entry
+ * @entry: struct hist_entry to use as a loop cursor
+ * @next: struct hist_entry to use as temporary storage
+ * @hists: struct hists entry that points to an rb_root tree
+ */
+#define hist__for_each_entry_in_safe(entry, next, hists) \
+ __hist__for_each_entry_safe(entry, next, hists__get_root(hists), rb_node_in)
+
+/**
+ * hist__for_each_entry_out - iterate thru all the output entries in hist
+ * @entry: struct hist_entry to use as a loop cursor
+ * @hists: struct hists entry that points to an rb_root tree
+ */
+#define hist__for_each_entry_out(entry, hists) \
+ __hist__for_each_entry(entry, (&hists->entries), rb_node)
+
enum sort_mode {
SORT_MODE__NORMAL,
SORT_MODE__BRANCH,
--
1.7.11.7
next prev parent reply other threads:[~2014-04-10 20:13 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-10 20:10 [RFC 0/5] perf: Create hist_entry groups Don Zickus
2014-04-10 20:10 ` [RFC 1/5] perf: Wrap __hists__add_entry to prep for group entry change Don Zickus
2014-04-10 20:10 ` Don Zickus [this message]
2014-04-10 20:10 ` [RFC 3/5] perf: Add in stub hist_entry_group code Don Zickus
2014-04-10 20:11 ` [RFC 4/5] perf: Switch to using hist_entry_group Don Zickus
2014-04-10 20:11 ` [RFC 5/5] perf: Enable multiple hist_entry_group output Don Zickus
2014-04-11 17:30 ` Jiri Olsa
2014-04-11 18:28 ` Don Zickus
2014-04-11 18:34 ` Don Zickus
2014-04-14 9:19 ` Jiri Olsa
2014-04-14 14:13 ` Don Zickus
2014-04-15 3:01 ` [RFC 0/5] perf: Create hist_entry groups Namhyung Kim
2014-04-15 9:40 ` Jiri Olsa
2014-04-15 11:35 ` Namhyung Kim
2014-04-15 16:08 ` Don Zickus
2014-04-16 8:29 ` Namhyung Kim
2014-04-21 20:07 ` Don Zickus
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1397160661-33395-3-git-send-email-dzickus@redhat.com \
--to=dzickus@redhat.com \
--cc=acme@kernel.org \
--cc=andi@firstfloor.org \
--cc=eranian@google.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=namhyung@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.