diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-05-10 12:04:11 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-05-10 12:13:49 -0400 |
commit | 1c02c4d2e92f2097f1bba63ec71560b0e05a7f36 (patch) | |
tree | ad2a722931398ce3cd3ae850c4cfa148558a52ea | |
parent | d118f8ba6ac2af2bf11d40cba657c813f0f39ca2 (diff) |
perf hist: Introduce hists class and move lots of methods to it
In cbbc79a 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: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/builtin-annotate.c | 17 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 50 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 71 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 2 | ||||
-rw-r--r-- | tools/perf/util/event.c | 2 | ||||
-rw-r--r-- | tools/perf/util/event.h | 14 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 92 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 48 | ||||
-rw-r--r-- | tools/perf/util/session.c | 2 | ||||
-rw-r--r-- | tools/perf/util/session.h | 12 |
10 files changed, 146 insertions, 164 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index c7ac45a59ed5..3940964161b3 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -96,8 +96,7 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) | |||
96 | return 0; | 96 | return 0; |
97 | } | 97 | } |
98 | 98 | ||
99 | static int perf_session__add_hist_entry(struct perf_session *self, | 99 | static int hists__add_entry(struct hists *self, struct addr_location *al) |
100 | struct addr_location *al) | ||
101 | { | 100 | { |
102 | struct hist_entry *he; | 101 | struct hist_entry *he; |
103 | 102 | ||
@@ -112,7 +111,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, | |||
112 | return 0; | 111 | return 0; |
113 | } | 112 | } |
114 | 113 | ||
115 | he = __perf_session__add_hist_entry(&self->hists, al, NULL, 1); | 114 | he = __hists__add_entry(self, al, NULL, 1); |
116 | if (he == NULL) | 115 | if (he == NULL) |
117 | return -ENOMEM; | 116 | return -ENOMEM; |
118 | 117 | ||
@@ -132,7 +131,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
132 | return -1; | 131 | return -1; |
133 | } | 132 | } |
134 | 133 | ||
135 | if (!al.filtered && perf_session__add_hist_entry(session, &al)) { | 134 | if (!al.filtered && hists__add_entry(&session->hists, &al)) { |
136 | pr_warning("problem incrementing symbol count, " | 135 | pr_warning("problem incrementing symbol count, " |
137 | "skipping event\n"); | 136 | "skipping event\n"); |
138 | return -1; | 137 | return -1; |
@@ -514,11 +513,11 @@ static void annotate_sym(struct hist_entry *he) | |||
514 | free_source_line(he, len); | 513 | free_source_line(he, len); |
515 | } | 514 | } |
516 | 515 | ||
517 | static void perf_session__find_annotations(struct perf_session *self) | 516 | static void hists__find_annotations(struct hists *self) |
518 | { | 517 | { |
519 | struct rb_node *nd; | 518 | struct rb_node *nd; |
520 | 519 | ||
521 | for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) { | 520 | for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { |
522 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); | 521 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); |
523 | struct sym_priv *priv; | 522 | struct sym_priv *priv; |
524 | 523 | ||
@@ -570,9 +569,9 @@ static int __cmd_annotate(void) | |||
570 | if (verbose > 2) | 569 | if (verbose > 2) |
571 | perf_session__fprintf_dsos(session, stdout); | 570 | perf_session__fprintf_dsos(session, stdout); |
572 | 571 | ||
573 | perf_session__collapse_resort(&session->hists); | 572 | hists__collapse_resort(&session->hists); |
574 | perf_session__output_resort(&session->hists, session->event_total[0]); | 573 | hists__output_resort(&session->hists); |
575 | perf_session__find_annotations(session); | 574 | hists__find_annotations(&session->hists); |
576 | out_delete: | 575 | out_delete: |
577 | perf_session__delete(session); | 576 | perf_session__delete(session); |
578 | 577 | ||
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 613a5c4f6d83..3a95a0260a5b 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -22,10 +22,10 @@ static char diff__default_sort_order[] = "dso,symbol"; | |||
22 | static bool force; | 22 | static bool force; |
23 | static bool show_displacement; | 23 | static bool show_displacement; |
24 | 24 | ||
25 | static int perf_session__add_hist_entry(struct perf_session *self, | 25 | static int hists__add_entry(struct hists *self, |
26 | struct addr_location *al, u64 count) | 26 | struct addr_location *al, u64 count) |
27 | { | 27 | { |
28 | if (__perf_session__add_hist_entry(&self->hists, al, NULL, count) != NULL) | 28 | if (__hists__add_entry(self, al, NULL, count) != NULL) |
29 | return 0; | 29 | return 0; |
30 | return -ENOMEM; | 30 | return -ENOMEM; |
31 | } | 31 | } |
@@ -49,12 +49,12 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi | |||
49 | 49 | ||
50 | event__parse_sample(event, session->sample_type, &data); | 50 | event__parse_sample(event, session->sample_type, &data); |
51 | 51 | ||
52 | if (perf_session__add_hist_entry(session, &al, data.period)) { | 52 | if (hists__add_entry(&session->hists, &al, data.period)) { |
53 | pr_warning("problem incrementing symbol count, skipping event\n"); | 53 | pr_warning("problem incrementing symbol count, skipping event\n"); |
54 | return -1; | 54 | return -1; |
55 | } | 55 | } |
56 | 56 | ||
57 | session->events_stats.total += data.period; | 57 | session->hists.stats.total += data.period; |
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
@@ -87,35 +87,34 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root, | |||
87 | rb_insert_color(&he->rb_node, root); | 87 | rb_insert_color(&he->rb_node, root); |
88 | } | 88 | } |
89 | 89 | ||
90 | static void perf_session__resort_hist_entries(struct perf_session *self) | 90 | static void hists__resort_entries(struct hists *self) |
91 | { | 91 | { |
92 | unsigned long position = 1; | 92 | unsigned long position = 1; |
93 | struct rb_root tmp = RB_ROOT; | 93 | struct rb_root tmp = RB_ROOT; |
94 | struct rb_node *next = rb_first(&self->hists); | 94 | struct rb_node *next = rb_first(&self->entries); |
95 | 95 | ||
96 | while (next != NULL) { | 96 | while (next != NULL) { |
97 | struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); | 97 | struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); |
98 | 98 | ||
99 | next = rb_next(&n->rb_node); | 99 | next = rb_next(&n->rb_node); |
100 | rb_erase(&n->rb_node, &self->hists); | 100 | rb_erase(&n->rb_node, &self->entries); |
101 | n->position = position++; | 101 | n->position = position++; |
102 | perf_session__insert_hist_entry_by_name(&tmp, n); | 102 | perf_session__insert_hist_entry_by_name(&tmp, n); |
103 | } | 103 | } |
104 | 104 | ||
105 | self->hists = tmp; | 105 | self->entries = tmp; |
106 | } | 106 | } |
107 | 107 | ||
108 | static void perf_session__set_hist_entries_positions(struct perf_session *self) | 108 | static void hists__set_positions(struct hists *self) |
109 | { | 109 | { |
110 | perf_session__output_resort(&self->hists, self->events_stats.total); | 110 | hists__output_resort(self); |
111 | perf_session__resort_hist_entries(self); | 111 | hists__resort_entries(self); |
112 | } | 112 | } |
113 | 113 | ||
114 | static struct hist_entry * | 114 | static struct hist_entry *hists__find_entry(struct hists *self, |
115 | perf_session__find_hist_entry(struct perf_session *self, | 115 | struct hist_entry *he) |
116 | struct hist_entry *he) | ||
117 | { | 116 | { |
118 | struct rb_node *n = self->hists.rb_node; | 117 | struct rb_node *n = self->entries.rb_node; |
119 | 118 | ||
120 | while (n) { | 119 | while (n) { |
121 | struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node); | 120 | 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, | |||
132 | return NULL; | 131 | return NULL; |
133 | } | 132 | } |
134 | 133 | ||
135 | static void perf_session__match_hists(struct perf_session *old_session, | 134 | static void hists__match(struct hists *older, struct hists *newer) |
136 | struct perf_session *new_session) | ||
137 | { | 135 | { |
138 | struct rb_node *nd; | 136 | struct rb_node *nd; |
139 | 137 | ||
140 | for (nd = rb_first(&new_session->hists); nd; nd = rb_next(nd)) { | 138 | for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) { |
141 | struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node); | 139 | struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node); |
142 | pos->pair = perf_session__find_hist_entry(old_session, pos); | 140 | pos->pair = hists__find_entry(older, pos); |
143 | } | 141 | } |
144 | } | 142 | } |
145 | 143 | ||
@@ -159,15 +157,13 @@ static int __cmd_diff(void) | |||
159 | goto out_delete; | 157 | goto out_delete; |
160 | } | 158 | } |
161 | 159 | ||
162 | perf_session__output_resort(&session[1]->hists, | 160 | hists__output_resort(&session[1]->hists); |
163 | session[1]->events_stats.total); | ||
164 | if (show_displacement) | 161 | if (show_displacement) |
165 | perf_session__set_hist_entries_positions(session[0]); | 162 | hists__set_positions(&session[0]->hists); |
166 | 163 | ||
167 | perf_session__match_hists(session[0], session[1]); | 164 | hists__match(&session[0]->hists, &session[1]->hists); |
168 | perf_session__fprintf_hists(&session[1]->hists, session[0], | 165 | hists__fprintf(&session[1]->hists, &session[0]->hists, |
169 | show_displacement, stdout, | 166 | show_displacement, stdout); |
170 | session[1]->events_stats.total); | ||
171 | out_delete: | 167 | out_delete: |
172 | for (i = 0; i < 2; ++i) | 168 | for (i = 0; i < 2; ++i) |
173 | perf_session__delete(session[i]); | 169 | perf_session__delete(session[i]); |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 642a6d8eb5dc..53077fd973f0 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -44,16 +44,17 @@ static char *pretty_printing_style = default_pretty_printing_style; | |||
44 | 44 | ||
45 | static char callchain_default_opt[] = "fractal,0.5"; | 45 | static char callchain_default_opt[] = "fractal,0.5"; |
46 | 46 | ||
47 | static struct event_stat_id *get_stats(struct perf_session *self, | 47 | static struct hists *perf_session__hists_findnew(struct perf_session *self, |
48 | u64 event_stream, u32 type, u64 config) | 48 | u64 event_stream, u32 type, |
49 | u64 config) | ||
49 | { | 50 | { |
50 | struct rb_node **p = &self->stats_by_id.rb_node; | 51 | struct rb_node **p = &self->hists_tree.rb_node; |
51 | struct rb_node *parent = NULL; | 52 | struct rb_node *parent = NULL; |
52 | struct event_stat_id *iter, *new; | 53 | struct hists *iter, *new; |
53 | 54 | ||
54 | while (*p != NULL) { | 55 | while (*p != NULL) { |
55 | parent = *p; | 56 | parent = *p; |
56 | iter = rb_entry(parent, struct event_stat_id, rb_node); | 57 | iter = rb_entry(parent, struct hists, rb_node); |
57 | if (iter->config == config) | 58 | if (iter->config == config) |
58 | return iter; | 59 | return iter; |
59 | 60 | ||
@@ -64,15 +65,15 @@ static struct event_stat_id *get_stats(struct perf_session *self, | |||
64 | p = &(*p)->rb_left; | 65 | p = &(*p)->rb_left; |
65 | } | 66 | } |
66 | 67 | ||
67 | new = malloc(sizeof(struct event_stat_id)); | 68 | new = malloc(sizeof(struct hists)); |
68 | if (new == NULL) | 69 | if (new == NULL) |
69 | return NULL; | 70 | return NULL; |
70 | memset(new, 0, sizeof(struct event_stat_id)); | 71 | memset(new, 0, sizeof(struct hists)); |
71 | new->event_stream = event_stream; | 72 | new->event_stream = event_stream; |
72 | new->config = config; | 73 | new->config = config; |
73 | new->type = type; | 74 | new->type = type; |
74 | rb_link_node(&new->rb_node, parent, p); | 75 | rb_link_node(&new->rb_node, parent, p); |
75 | rb_insert_color(&new->rb_node, &self->stats_by_id); | 76 | rb_insert_color(&new->rb_node, &self->hists_tree); |
76 | return new; | 77 | return new; |
77 | } | 78 | } |
78 | 79 | ||
@@ -84,7 +85,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, | |||
84 | struct symbol *parent = NULL; | 85 | struct symbol *parent = NULL; |
85 | int err = -ENOMEM; | 86 | int err = -ENOMEM; |
86 | struct hist_entry *he; | 87 | struct hist_entry *he; |
87 | struct event_stat_id *stats; | 88 | struct hists *hists; |
88 | struct perf_event_attr *attr; | 89 | struct perf_event_attr *attr; |
89 | 90 | ||
90 | if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) { | 91 | 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, | |||
96 | 97 | ||
97 | attr = perf_header__find_attr(data->id, &self->header); | 98 | attr = perf_header__find_attr(data->id, &self->header); |
98 | if (attr) | 99 | if (attr) |
99 | stats = get_stats(self, data->id, attr->type, attr->config); | 100 | hists = perf_session__hists_findnew(self, data->id, attr->type, attr->config); |
100 | else | 101 | else |
101 | stats = get_stats(self, data->id, 0, 0); | 102 | hists = perf_session__hists_findnew(self, data->id, 0, 0); |
102 | if (stats == NULL) | 103 | if (hists == NULL) |
103 | goto out_free_syms; | 104 | goto out_free_syms; |
104 | he = __perf_session__add_hist_entry(&stats->hists, al, parent, | 105 | he = __hists__add_entry(hists, al, parent, data->period); |
105 | data->period); | ||
106 | if (he == NULL) | 106 | if (he == NULL) |
107 | goto out_free_syms; | 107 | goto out_free_syms; |
108 | err = 0; | 108 | err = 0; |
@@ -117,18 +117,19 @@ static int add_event_total(struct perf_session *session, | |||
117 | struct sample_data *data, | 117 | struct sample_data *data, |
118 | struct perf_event_attr *attr) | 118 | struct perf_event_attr *attr) |
119 | { | 119 | { |
120 | struct event_stat_id *stats; | 120 | struct hists *hists; |
121 | 121 | ||
122 | if (attr) | 122 | if (attr) |
123 | stats = get_stats(session, data->id, attr->type, attr->config); | 123 | hists = perf_session__hists_findnew(session, data->id, |
124 | attr->type, attr->config); | ||
124 | else | 125 | else |
125 | stats = get_stats(session, data->id, 0, 0); | 126 | hists = perf_session__hists_findnew(session, data->id, 0, 0); |
126 | 127 | ||
127 | if (!stats) | 128 | if (!hists) |
128 | return -ENOMEM; | 129 | return -ENOMEM; |
129 | 130 | ||
130 | stats->stats.total += data->period; | 131 | hists->stats.total += data->period; |
131 | session->events_stats.total += data->period; | 132 | session->hists.stats.total += data->period; |
132 | return 0; | 133 | return 0; |
133 | } | 134 | } |
134 | 135 | ||
@@ -292,35 +293,33 @@ static int __cmd_report(void) | |||
292 | if (verbose > 2) | 293 | if (verbose > 2) |
293 | perf_session__fprintf_dsos(session, stdout); | 294 | perf_session__fprintf_dsos(session, stdout); |
294 | 295 | ||
295 | next = rb_first(&session->stats_by_id); | 296 | next = rb_first(&session->hists_tree); |
296 | while (next) { | 297 | while (next) { |
297 | struct event_stat_id *stats; | 298 | struct hists *hists; |
298 | u64 nr_hists; | 299 | u64 nr_hists; |
299 | 300 | ||
300 | stats = rb_entry(next, struct event_stat_id, rb_node); | 301 | hists = rb_entry(next, struct hists, rb_node); |
301 | perf_session__collapse_resort(&stats->hists); | 302 | hists__collapse_resort(hists); |
302 | nr_hists = perf_session__output_resort(&stats->hists, | 303 | nr_hists = hists__output_resort(hists); |
303 | stats->stats.total); | ||
304 | if (use_browser) | 304 | if (use_browser) |
305 | perf_session__browse_hists(&stats->hists, nr_hists, | 305 | perf_session__browse_hists(&hists->entries, nr_hists, |
306 | stats->stats.total, help, | 306 | hists->stats.total, help, |
307 | input_name); | 307 | input_name); |
308 | else { | 308 | else { |
309 | if (rb_first(&session->stats_by_id) == | 309 | if (rb_first(&session->hists.entries) == |
310 | rb_last(&session->stats_by_id)) | 310 | rb_last(&session->hists.entries)) |
311 | fprintf(stdout, "# Samples: %Ld\n#\n", | 311 | fprintf(stdout, "# Samples: %Ld\n#\n", |
312 | stats->stats.total); | 312 | hists->stats.total); |
313 | else | 313 | else |
314 | fprintf(stdout, "# Samples: %Ld %s\n#\n", | 314 | fprintf(stdout, "# Samples: %Ld %s\n#\n", |
315 | stats->stats.total, | 315 | hists->stats.total, |
316 | __event_name(stats->type, stats->config)); | 316 | __event_name(hists->type, hists->config)); |
317 | 317 | ||
318 | perf_session__fprintf_hists(&stats->hists, NULL, false, stdout, | 318 | hists__fprintf(hists, NULL, false, stdout); |
319 | stats->stats.total); | ||
320 | fprintf(stdout, "\n\n"); | 319 | fprintf(stdout, "\n\n"); |
321 | } | 320 | } |
322 | 321 | ||
323 | next = rb_next(&stats->rb_node); | 322 | next = rb_next(&hists->rb_node); |
324 | } | 323 | } |
325 | 324 | ||
326 | if (!use_browser && sort_order == default_sort_order && | 325 | if (!use_browser && sort_order == default_sort_order && |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 9c483e92e8db..6e268ca761e9 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -107,7 +107,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
107 | data.time, thread->comm); | 107 | data.time, thread->comm); |
108 | } | 108 | } |
109 | 109 | ||
110 | session->events_stats.total += data.period; | 110 | session->hists.stats.total += data.period; |
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index d2ea9dd9fdf1..cce006ec8f05 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -368,7 +368,7 @@ int event__process_comm(event_t *self, struct perf_session *session) | |||
368 | int event__process_lost(event_t *self, struct perf_session *session) | 368 | int event__process_lost(event_t *self, struct perf_session *session) |
369 | { | 369 | { |
370 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); | 370 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); |
371 | session->events_stats.lost += self->lost.lost; | 371 | session->hists.stats.lost += self->lost.lost; |
372 | return 0; | 372 | return 0; |
373 | } | 373 | } |
374 | 374 | ||
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 6cc1b1dced55..48c2cc9dae4f 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -131,20 +131,6 @@ typedef union event_union { | |||
131 | struct build_id_event build_id; | 131 | struct build_id_event build_id; |
132 | } event_t; | 132 | } event_t; |
133 | 133 | ||
134 | struct events_stats { | ||
135 | u64 total; | ||
136 | u64 lost; | ||
137 | }; | ||
138 | |||
139 | struct event_stat_id { | ||
140 | struct rb_node rb_node; | ||
141 | struct rb_root hists; | ||
142 | struct events_stats stats; | ||
143 | u64 config; | ||
144 | u64 event_stream; | ||
145 | u32 type; | ||
146 | }; | ||
147 | |||
148 | void event__print_totals(void); | 134 | void event__print_totals(void); |
149 | 135 | ||
150 | struct perf_session; | 136 | struct perf_session; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 0f154a530dfd..410cf56c9662 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -8,21 +8,21 @@ struct callchain_param callchain_param = { | |||
8 | .min_percent = 0.5 | 8 | .min_percent = 0.5 |
9 | }; | 9 | }; |
10 | 10 | ||
11 | static void perf_session__add_cpumode_count(struct hist_entry *he, | 11 | static void hist_entry__add_cpumode_count(struct hist_entry *self, |
12 | unsigned int cpumode, u64 count) | 12 | unsigned int cpumode, u64 count) |
13 | { | 13 | { |
14 | switch (cpumode) { | 14 | switch (cpumode) { |
15 | case PERF_RECORD_MISC_KERNEL: | 15 | case PERF_RECORD_MISC_KERNEL: |
16 | he->count_sys += count; | 16 | self->count_sys += count; |
17 | break; | 17 | break; |
18 | case PERF_RECORD_MISC_USER: | 18 | case PERF_RECORD_MISC_USER: |
19 | he->count_us += count; | 19 | self->count_us += count; |
20 | break; | 20 | break; |
21 | case PERF_RECORD_MISC_GUEST_KERNEL: | 21 | case PERF_RECORD_MISC_GUEST_KERNEL: |
22 | he->count_guest_sys += count; | 22 | self->count_guest_sys += count; |
23 | break; | 23 | break; |
24 | case PERF_RECORD_MISC_GUEST_USER: | 24 | case PERF_RECORD_MISC_GUEST_USER: |
25 | he->count_guest_us += count; | 25 | self->count_guest_us += count; |
26 | break; | 26 | break; |
27 | default: | 27 | default: |
28 | break; | 28 | break; |
@@ -47,12 +47,11 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) | |||
47 | return self; | 47 | return self; |
48 | } | 48 | } |
49 | 49 | ||
50 | struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, | 50 | struct hist_entry *__hists__add_entry(struct hists *self, |
51 | struct addr_location *al, | 51 | struct addr_location *al, |
52 | struct symbol *sym_parent, | 52 | struct symbol *sym_parent, u64 count) |
53 | u64 count) | ||
54 | { | 53 | { |
55 | struct rb_node **p = &hists->rb_node; | 54 | struct rb_node **p = &self->entries.rb_node; |
56 | struct rb_node *parent = NULL; | 55 | struct rb_node *parent = NULL; |
57 | struct hist_entry *he; | 56 | struct hist_entry *he; |
58 | struct hist_entry entry = { | 57 | struct hist_entry entry = { |
@@ -89,9 +88,9 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, | |||
89 | if (!he) | 88 | if (!he) |
90 | return NULL; | 89 | return NULL; |
91 | rb_link_node(&he->rb_node, parent, p); | 90 | rb_link_node(&he->rb_node, parent, p); |
92 | rb_insert_color(&he->rb_node, hists); | 91 | rb_insert_color(&he->rb_node, &self->entries); |
93 | out: | 92 | out: |
94 | perf_session__add_cpumode_count(he, al->cpumode, count); | 93 | hist_entry__add_cpumode_count(he, al->cpumode, count); |
95 | return he; | 94 | return he; |
96 | } | 95 | } |
97 | 96 | ||
@@ -167,7 +166,7 @@ static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he) | |||
167 | rb_insert_color(&he->rb_node, root); | 166 | rb_insert_color(&he->rb_node, root); |
168 | } | 167 | } |
169 | 168 | ||
170 | void perf_session__collapse_resort(struct rb_root *hists) | 169 | void hists__collapse_resort(struct hists *self) |
171 | { | 170 | { |
172 | struct rb_root tmp; | 171 | struct rb_root tmp; |
173 | struct rb_node *next; | 172 | struct rb_node *next; |
@@ -177,28 +176,28 @@ void perf_session__collapse_resort(struct rb_root *hists) | |||
177 | return; | 176 | return; |
178 | 177 | ||
179 | tmp = RB_ROOT; | 178 | tmp = RB_ROOT; |
180 | next = rb_first(hists); | 179 | next = rb_first(&self->entries); |
181 | 180 | ||
182 | while (next) { | 181 | while (next) { |
183 | n = rb_entry(next, struct hist_entry, rb_node); | 182 | n = rb_entry(next, struct hist_entry, rb_node); |
184 | next = rb_next(&n->rb_node); | 183 | next = rb_next(&n->rb_node); |
185 | 184 | ||
186 | rb_erase(&n->rb_node, hists); | 185 | rb_erase(&n->rb_node, &self->entries); |
187 | collapse__insert_entry(&tmp, n); | 186 | collapse__insert_entry(&tmp, n); |
188 | } | 187 | } |
189 | 188 | ||
190 | *hists = tmp; | 189 | self->entries = tmp; |
191 | } | 190 | } |
192 | 191 | ||
193 | /* | 192 | /* |
194 | * reverse the map, sort on count. | 193 | * reverse the map, sort on count. |
195 | */ | 194 | */ |
196 | 195 | ||
197 | static void perf_session__insert_output_hist_entry(struct rb_root *root, | 196 | static void __hists__insert_output_entry(struct rb_root *entries, |
198 | struct hist_entry *he, | 197 | struct hist_entry *he, |
199 | u64 min_callchain_hits) | 198 | u64 min_callchain_hits) |
200 | { | 199 | { |
201 | struct rb_node **p = &root->rb_node; | 200 | struct rb_node **p = &entries->rb_node; |
202 | struct rb_node *parent = NULL; | 201 | struct rb_node *parent = NULL; |
203 | struct hist_entry *iter; | 202 | struct hist_entry *iter; |
204 | 203 | ||
@@ -217,10 +216,10 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root, | |||
217 | } | 216 | } |
218 | 217 | ||
219 | rb_link_node(&he->rb_node, parent, p); | 218 | rb_link_node(&he->rb_node, parent, p); |
220 | rb_insert_color(&he->rb_node, root); | 219 | rb_insert_color(&he->rb_node, entries); |
221 | } | 220 | } |
222 | 221 | ||
223 | u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) | 222 | u64 hists__output_resort(struct hists *self) |
224 | { | 223 | { |
225 | struct rb_root tmp; | 224 | struct rb_root tmp; |
226 | struct rb_node *next; | 225 | struct rb_node *next; |
@@ -228,23 +227,21 @@ u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) | |||
228 | u64 min_callchain_hits; | 227 | u64 min_callchain_hits; |
229 | u64 nr_hists = 0; | 228 | u64 nr_hists = 0; |
230 | 229 | ||
231 | min_callchain_hits = | 230 | min_callchain_hits = self->stats.total * (callchain_param.min_percent / 100); |
232 | total_samples * (callchain_param.min_percent / 100); | ||
233 | 231 | ||
234 | tmp = RB_ROOT; | 232 | tmp = RB_ROOT; |
235 | next = rb_first(hists); | 233 | next = rb_first(&self->entries); |
236 | 234 | ||
237 | while (next) { | 235 | while (next) { |
238 | n = rb_entry(next, struct hist_entry, rb_node); | 236 | n = rb_entry(next, struct hist_entry, rb_node); |
239 | next = rb_next(&n->rb_node); | 237 | next = rb_next(&n->rb_node); |
240 | 238 | ||
241 | rb_erase(&n->rb_node, hists); | 239 | rb_erase(&n->rb_node, &self->entries); |
242 | perf_session__insert_output_hist_entry(&tmp, n, | 240 | __hists__insert_output_entry(&tmp, n, min_callchain_hits); |
243 | min_callchain_hits); | ||
244 | ++nr_hists; | 241 | ++nr_hists; |
245 | } | 242 | } |
246 | 243 | ||
247 | *hists = tmp; | 244 | self->entries = tmp; |
248 | return nr_hists; | 245 | return nr_hists; |
249 | } | 246 | } |
250 | 247 | ||
@@ -500,12 +497,9 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, | |||
500 | return ret; | 497 | return ret; |
501 | } | 498 | } |
502 | 499 | ||
503 | int hist_entry__snprintf(struct hist_entry *self, | 500 | int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, |
504 | char *s, size_t size, | 501 | struct hists *pair_hists, bool show_displacement, |
505 | struct perf_session *pair_session, | 502 | long displacement, bool color, u64 session_total) |
506 | bool show_displacement, | ||
507 | long displacement, bool color, | ||
508 | u64 session_total) | ||
509 | { | 503 | { |
510 | struct sort_entry *se; | 504 | struct sort_entry *se; |
511 | u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us; | 505 | u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us; |
@@ -515,9 +509,9 @@ int hist_entry__snprintf(struct hist_entry *self, | |||
515 | if (symbol_conf.exclude_other && !self->parent) | 509 | if (symbol_conf.exclude_other && !self->parent) |
516 | return 0; | 510 | return 0; |
517 | 511 | ||
518 | if (pair_session) { | 512 | if (pair_hists) { |
519 | count = self->pair ? self->pair->count : 0; | 513 | count = self->pair ? self->pair->count : 0; |
520 | total = pair_session->events_stats.total; | 514 | total = pair_hists->stats.total; |
521 | count_sys = self->pair ? self->pair->count_sys : 0; | 515 | count_sys = self->pair ? self->pair->count_sys : 0; |
522 | count_us = self->pair ? self->pair->count_us : 0; | 516 | count_us = self->pair ? self->pair->count_us : 0; |
523 | count_guest_sys = self->pair ? self->pair->count_guest_sys : 0; | 517 | count_guest_sys = self->pair ? self->pair->count_guest_sys : 0; |
@@ -569,7 +563,7 @@ int hist_entry__snprintf(struct hist_entry *self, | |||
569 | ret += snprintf(s + ret, size - ret, "%11lld", count); | 563 | ret += snprintf(s + ret, size - ret, "%11lld", count); |
570 | } | 564 | } |
571 | 565 | ||
572 | if (pair_session) { | 566 | if (pair_hists) { |
573 | char bf[32]; | 567 | char bf[32]; |
574 | double old_percent = 0, new_percent = 0, diff; | 568 | double old_percent = 0, new_percent = 0, diff; |
575 | 569 | ||
@@ -615,14 +609,12 @@ int hist_entry__snprintf(struct hist_entry *self, | |||
615 | return ret; | 609 | return ret; |
616 | } | 610 | } |
617 | 611 | ||
618 | int hist_entry__fprintf(struct hist_entry *self, | 612 | int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists, |
619 | struct perf_session *pair_session, | 613 | bool show_displacement, long displacement, FILE *fp, |
620 | bool show_displacement, | ||
621 | long displacement, FILE *fp, | ||
622 | u64 session_total) | 614 | u64 session_total) |
623 | { | 615 | { |
624 | char bf[512]; | 616 | char bf[512]; |
625 | hist_entry__snprintf(self, bf, sizeof(bf), pair_session, | 617 | hist_entry__snprintf(self, bf, sizeof(bf), pair_hists, |
626 | show_displacement, displacement, | 618 | show_displacement, displacement, |
627 | true, session_total); | 619 | true, session_total); |
628 | return fprintf(fp, "%s\n", bf); | 620 | return fprintf(fp, "%s\n", bf); |
@@ -644,10 +636,8 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp, | |||
644 | left_margin); | 636 | left_margin); |
645 | } | 637 | } |
646 | 638 | ||
647 | size_t perf_session__fprintf_hists(struct rb_root *hists, | 639 | size_t hists__fprintf(struct hists *self, struct hists *pair, |
648 | struct perf_session *pair, | 640 | bool show_displacement, FILE *fp) |
649 | bool show_displacement, FILE *fp, | ||
650 | u64 session_total) | ||
651 | { | 641 | { |
652 | struct sort_entry *se; | 642 | struct sort_entry *se; |
653 | struct rb_node *nd; | 643 | struct rb_node *nd; |
@@ -753,7 +743,7 @@ size_t perf_session__fprintf_hists(struct rb_root *hists, | |||
753 | fprintf(fp, "\n#\n"); | 743 | fprintf(fp, "\n#\n"); |
754 | 744 | ||
755 | print_entries: | 745 | print_entries: |
756 | for (nd = rb_first(hists); nd; nd = rb_next(nd)) { | 746 | for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { |
757 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 747 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
758 | 748 | ||
759 | if (show_displacement) { | 749 | if (show_displacement) { |
@@ -765,10 +755,10 @@ print_entries: | |||
765 | ++position; | 755 | ++position; |
766 | } | 756 | } |
767 | ret += hist_entry__fprintf(h, pair, show_displacement, | 757 | ret += hist_entry__fprintf(h, pair, show_displacement, |
768 | displacement, fp, session_total); | 758 | displacement, fp, self->stats.total); |
769 | 759 | ||
770 | if (symbol_conf.use_callchain) | 760 | if (symbol_conf.use_callchain) |
771 | ret += hist_entry__fprintf_callchain(h, fp, session_total); | 761 | ret += hist_entry__fprintf_callchain(h, fp, self->stats.total); |
772 | 762 | ||
773 | if (h->ms.map == NULL && verbose > 1) { | 763 | if (h->ms.map == NULL && verbose > 1) { |
774 | __map_groups__fprintf_maps(&h->thread->mg, | 764 | __map_groups__fprintf_maps(&h->thread->mg, |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b49013adb34b..bdde81eca69f 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -6,34 +6,40 @@ | |||
6 | 6 | ||
7 | extern struct callchain_param callchain_param; | 7 | extern struct callchain_param callchain_param; |
8 | 8 | ||
9 | struct perf_session; | ||
10 | struct hist_entry; | 9 | struct hist_entry; |
11 | struct addr_location; | 10 | struct addr_location; |
12 | struct symbol; | 11 | struct symbol; |
13 | struct rb_root; | 12 | struct rb_root; |
14 | 13 | ||
15 | struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, | 14 | struct events_stats { |
16 | struct addr_location *al, | 15 | u64 total; |
17 | struct symbol *parent, | 16 | u64 lost; |
18 | u64 count); | 17 | }; |
18 | |||
19 | struct hists { | ||
20 | struct rb_node rb_node; | ||
21 | struct rb_root entries; | ||
22 | struct events_stats stats; | ||
23 | u64 config; | ||
24 | u64 event_stream; | ||
25 | u32 type; | ||
26 | }; | ||
27 | |||
28 | struct hist_entry *__hists__add_entry(struct hists *self, | ||
29 | struct addr_location *al, | ||
30 | struct symbol *parent, u64 count); | ||
19 | extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); | 31 | extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); |
20 | extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); | 32 | extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); |
21 | int hist_entry__fprintf(struct hist_entry *self, | 33 | int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists, |
22 | struct perf_session *pair_session, | 34 | bool show_displacement, long displacement, FILE *fp, |
23 | bool show_displacement, | 35 | u64 total); |
24 | long displacement, FILE *fp, | 36 | int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, |
25 | u64 session_total); | 37 | struct hists *pair_hists, bool show_displacement, |
26 | int hist_entry__snprintf(struct hist_entry *self, | 38 | long displacement, bool color, u64 total); |
27 | char *bf, size_t size, | ||
28 | struct perf_session *pair_session, | ||
29 | bool show_displacement, long displacement, | ||
30 | bool color, u64 session_total); | ||
31 | void hist_entry__free(struct hist_entry *); | 39 | void hist_entry__free(struct hist_entry *); |
32 | 40 | ||
33 | u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples); | 41 | u64 hists__output_resort(struct hists *self); |
34 | void perf_session__collapse_resort(struct rb_root *hists); | 42 | void hists__collapse_resort(struct hists *self); |
35 | size_t perf_session__fprintf_hists(struct rb_root *hists, | 43 | size_t hists__fprintf(struct hists *self, struct hists *pair, |
36 | struct perf_session *pair, | 44 | bool show_displacement, FILE *fp); |
37 | bool show_displacement, FILE *fp, | ||
38 | u64 session_total); | ||
39 | #endif /* __PERF_HIST_H */ | 45 | #endif /* __PERF_HIST_H */ |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 4130036a0109..72a7f6ae0293 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -89,7 +89,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc | |||
89 | 89 | ||
90 | memcpy(self->filename, filename, len); | 90 | memcpy(self->filename, filename, len); |
91 | self->threads = RB_ROOT; | 91 | self->threads = RB_ROOT; |
92 | self->stats_by_id = RB_ROOT; | 92 | self->hists_tree = RB_ROOT; |
93 | self->last_match = NULL; | 93 | self->last_match = NULL; |
94 | self->mmap_window = 32; | 94 | self->mmap_window = 32; |
95 | self->cwd = NULL; | 95 | self->cwd = NULL; |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 242d528bfae2..46190f94b547 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef __PERF_SESSION_H | 1 | #ifndef __PERF_SESSION_H |
2 | #define __PERF_SESSION_H | 2 | #define __PERF_SESSION_H |
3 | 3 | ||
4 | #include "hist.h" | ||
4 | #include "event.h" | 5 | #include "event.h" |
5 | #include "header.h" | 6 | #include "header.h" |
6 | #include "symbol.h" | 7 | #include "symbol.h" |
@@ -28,11 +29,16 @@ struct perf_session { | |||
28 | struct thread *last_match; | 29 | struct thread *last_match; |
29 | struct machine host_machine; | 30 | struct machine host_machine; |
30 | struct rb_root machines; | 31 | struct rb_root machines; |
31 | struct events_stats events_stats; | 32 | struct rb_root hists_tree; |
32 | struct rb_root stats_by_id; | ||
33 | unsigned long event_total[PERF_RECORD_MAX]; | 33 | unsigned long event_total[PERF_RECORD_MAX]; |
34 | unsigned long unknown_events; | 34 | unsigned long unknown_events; |
35 | struct rb_root hists; | 35 | /* |
36 | * FIXME: should point to the first entry in hists_tree and | ||
37 | * be a hists instance. Right now its only 'report' | ||
38 | * that is using ->hists_tree while all the rest use | ||
39 | * ->hists. | ||
40 | */ | ||
41 | struct hists hists; | ||
36 | u64 sample_type; | 42 | u64 sample_type; |
37 | int fd; | 43 | int fd; |
38 | bool fd_pipe; | 44 | bool fd_pipe; |