aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-05-10 12:04:11 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-05-10 12:13:49 -0400
commit1c02c4d2e92f2097f1bba63ec71560b0e05a7f36 (patch)
treead2a722931398ce3cd3ae850c4cfa148558a52ea /tools/perf
parentd118f8ba6ac2af2bf11d40cba657c813f0f39ca2 (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>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-annotate.c17
-rw-r--r--tools/perf/builtin-diff.c50
-rw-r--r--tools/perf/builtin-report.c71
-rw-r--r--tools/perf/builtin-trace.c2
-rw-r--r--tools/perf/util/event.c2
-rw-r--r--tools/perf/util/event.h14
-rw-r--r--tools/perf/util/hist.c92
-rw-r--r--tools/perf/util/hist.h48
-rw-r--r--tools/perf/util/session.c2
-rw-r--r--tools/perf/util/session.h12
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
99static int perf_session__add_hist_entry(struct perf_session *self, 99static 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
517static void perf_session__find_annotations(struct perf_session *self) 516static 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);
576out_delete: 575out_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";
22static bool force; 22static bool force;
23static bool show_displacement; 23static bool show_displacement;
24 24
25static int perf_session__add_hist_entry(struct perf_session *self, 25static 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
90static void perf_session__resort_hist_entries(struct perf_session *self) 90static 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
108static void perf_session__set_hist_entries_positions(struct perf_session *self) 108static 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
114static struct hist_entry * 114static struct hist_entry *hists__find_entry(struct hists *self,
115perf_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
135static void perf_session__match_hists(struct perf_session *old_session, 134static 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);
171out_delete: 167out_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
45static char callchain_default_opt[] = "fractal,0.5"; 45static char callchain_default_opt[] = "fractal,0.5";
46 46
47static struct event_stat_id *get_stats(struct perf_session *self, 47static 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)
368int event__process_lost(event_t *self, struct perf_session *session) 368int 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
134struct events_stats {
135 u64 total;
136 u64 lost;
137};
138
139struct 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
148void event__print_totals(void); 134void event__print_totals(void);
149 135
150struct perf_session; 136struct 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
11static void perf_session__add_cpumode_count(struct hist_entry *he, 11static 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
50struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, 50struct 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);
93out: 92out:
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
170void perf_session__collapse_resort(struct rb_root *hists) 169void 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
197static void perf_session__insert_output_hist_entry(struct rb_root *root, 196static 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
223u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) 222u64 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
503int hist_entry__snprintf(struct hist_entry *self, 500int 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
618int hist_entry__fprintf(struct hist_entry *self, 612int 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
647size_t perf_session__fprintf_hists(struct rb_root *hists, 639size_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
755print_entries: 745print_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
7extern struct callchain_param callchain_param; 7extern struct callchain_param callchain_param;
8 8
9struct perf_session;
10struct hist_entry; 9struct hist_entry;
11struct addr_location; 10struct addr_location;
12struct symbol; 11struct symbol;
13struct rb_root; 12struct rb_root;
14 13
15struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, 14struct events_stats {
16 struct addr_location *al, 15 u64 total;
17 struct symbol *parent, 16 u64 lost;
18 u64 count); 17};
18
19struct 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
28struct hist_entry *__hists__add_entry(struct hists *self,
29 struct addr_location *al,
30 struct symbol *parent, u64 count);
19extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); 31extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
20extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 32extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
21int hist_entry__fprintf(struct hist_entry *self, 33int 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, 36int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size,
25 u64 session_total); 37 struct hists *pair_hists, bool show_displacement,
26int 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);
31void hist_entry__free(struct hist_entry *); 39void hist_entry__free(struct hist_entry *);
32 40
33u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples); 41u64 hists__output_resort(struct hists *self);
34void perf_session__collapse_resort(struct rb_root *hists); 42void hists__collapse_resort(struct hists *self);
35size_t perf_session__fprintf_hists(struct rb_root *hists, 43size_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;