aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/hist.c111
-rw-r--r--tools/perf/util/hist.h9
-rw-r--r--tools/perf/util/sort.h1
4 files changed, 92 insertions, 30 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e389815078d3..b46f6e4bff3c 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -39,6 +39,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
39 evsel->idx = idx; 39 evsel->idx = idx;
40 evsel->attr = *attr; 40 evsel->attr = *attr;
41 INIT_LIST_HEAD(&evsel->node); 41 INIT_LIST_HEAD(&evsel->node);
42 hists__init(&evsel->hists);
42} 43}
43 44
44struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) 45struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 32c90865940f..80fe30d90d72 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -118,6 +118,7 @@ static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
118 if (!h->filtered) { 118 if (!h->filtered) {
119 hists__calc_col_len(hists, h); 119 hists__calc_col_len(hists, h);
120 ++hists->nr_entries; 120 ++hists->nr_entries;
121 hists->stats.total_period += h->period;
121 } 122 }
122} 123}
123 124
@@ -132,7 +133,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
132 struct addr_location *al, 133 struct addr_location *al,
133 struct symbol *sym_parent, u64 period) 134 struct symbol *sym_parent, u64 period)
134{ 135{
135 struct rb_node **p = &hists->entries.rb_node; 136 struct rb_node **p;
136 struct rb_node *parent = NULL; 137 struct rb_node *parent = NULL;
137 struct hist_entry *he; 138 struct hist_entry *he;
138 struct hist_entry entry = { 139 struct hist_entry entry = {
@@ -150,9 +151,13 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
150 }; 151 };
151 int cmp; 152 int cmp;
152 153
154 pthread_mutex_lock(&hists->lock);
155
156 p = &hists->entries_in->rb_node;
157
153 while (*p != NULL) { 158 while (*p != NULL) {
154 parent = *p; 159 parent = *p;
155 he = rb_entry(parent, struct hist_entry, rb_node); 160 he = rb_entry(parent, struct hist_entry, rb_node_in);
156 161
157 cmp = hist_entry__cmp(&entry, he); 162 cmp = hist_entry__cmp(&entry, he);
158 163
@@ -170,12 +175,14 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
170 175
171 he = hist_entry__new(&entry); 176 he = hist_entry__new(&entry);
172 if (!he) 177 if (!he)
173 return NULL; 178 goto out_unlock;
174 rb_link_node(&he->rb_node, parent, p); 179
175 rb_insert_color(&he->rb_node, &hists->entries); 180 rb_link_node(&he->rb_node_in, parent, p);
176 hists__inc_nr_entries(hists, he); 181 rb_insert_color(&he->rb_node_in, hists->entries_in);
177out: 182out:
178 hist_entry__add_cpumode_period(he, al->cpumode, period); 183 hist_entry__add_cpumode_period(he, al->cpumode, period);
184out_unlock:
185 pthread_mutex_unlock(&hists->lock);
179 return he; 186 return he;
180} 187}
181 188
@@ -233,7 +240,7 @@ static bool hists__collapse_insert_entry(struct hists *hists,
233 240
234 while (*p != NULL) { 241 while (*p != NULL) {
235 parent = *p; 242 parent = *p;
236 iter = rb_entry(parent, struct hist_entry, rb_node); 243 iter = rb_entry(parent, struct hist_entry, rb_node_in);
237 244
238 cmp = hist_entry__collapse(iter, he); 245 cmp = hist_entry__collapse(iter, he);
239 246
@@ -254,35 +261,57 @@ static bool hists__collapse_insert_entry(struct hists *hists,
254 p = &(*p)->rb_right; 261 p = &(*p)->rb_right;
255 } 262 }
256 263
257 rb_link_node(&he->rb_node, parent, p); 264 rb_link_node(&he->rb_node_in, parent, p);
258 rb_insert_color(&he->rb_node, root); 265 rb_insert_color(&he->rb_node_in, root);
259 return true; 266 return true;
260} 267}
261 268
262void hists__collapse_resort(struct hists *hists) 269static struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
263{ 270{
264 struct rb_root tmp; 271 struct rb_root *root;
272
273 pthread_mutex_lock(&hists->lock);
274
275 root = hists->entries_in;
276 if (++hists->entries_in > &hists->entries_in_array[1])
277 hists->entries_in = &hists->entries_in_array[0];
278
279 pthread_mutex_unlock(&hists->lock);
280
281 return root;
282}
283
284static void __hists__collapse_resort(struct hists *hists, bool threaded)
285{
286 struct rb_root *root;
265 struct rb_node *next; 287 struct rb_node *next;
266 struct hist_entry *n; 288 struct hist_entry *n;
267 289
268 if (!sort__need_collapse) 290 if (!sort__need_collapse && !threaded)
269 return; 291 return;
270 292
271 tmp = RB_ROOT; 293 root = hists__get_rotate_entries_in(hists);
272 next = rb_first(&hists->entries); 294 next = rb_first(root);
273 hists->nr_entries = 0; 295 hists->stats.total_period = 0;
274 hists__reset_col_len(hists);
275 296
276 while (next) { 297 while (next) {
277 n = rb_entry(next, struct hist_entry, rb_node); 298 n = rb_entry(next, struct hist_entry, rb_node_in);
278 next = rb_next(&n->rb_node); 299 next = rb_next(&n->rb_node_in);
279 300
280 rb_erase(&n->rb_node, &hists->entries); 301 rb_erase(&n->rb_node_in, root);
281 if (hists__collapse_insert_entry(hists, &tmp, n)) 302 if (hists__collapse_insert_entry(hists, &hists->entries_collapsed, n))
282 hists__inc_nr_entries(hists, n); 303 hists__inc_nr_entries(hists, n);
283 } 304 }
305}
284 306
285 hists->entries = tmp; 307void hists__collapse_resort(struct hists *hists)
308{
309 return __hists__collapse_resort(hists, false);
310}
311
312void hists__collapse_resort_threaded(struct hists *hists)
313{
314 return __hists__collapse_resort(hists, true);
286} 315}
287 316
288/* 317/*
@@ -315,31 +344,43 @@ static void __hists__insert_output_entry(struct rb_root *entries,
315 rb_insert_color(&he->rb_node, entries); 344 rb_insert_color(&he->rb_node, entries);
316} 345}
317 346
318void hists__output_resort(struct hists *hists) 347static void __hists__output_resort(struct hists *hists, bool threaded)
319{ 348{
320 struct rb_root tmp; 349 struct rb_root *root;
321 struct rb_node *next; 350 struct rb_node *next;
322 struct hist_entry *n; 351 struct hist_entry *n;
323 u64 min_callchain_hits; 352 u64 min_callchain_hits;
324 353
325 min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100); 354 min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
326 355
327 tmp = RB_ROOT; 356 if (sort__need_collapse || threaded)
328 next = rb_first(&hists->entries); 357 root = &hists->entries_collapsed;
358 else
359 root = hists->entries_in;
360
361 next = rb_first(root);
362 hists->entries = RB_ROOT;
329 363
330 hists->nr_entries = 0; 364 hists->nr_entries = 0;
331 hists__reset_col_len(hists); 365 hists__reset_col_len(hists);
332 366
333 while (next) { 367 while (next) {
334 n = rb_entry(next, struct hist_entry, rb_node); 368 n = rb_entry(next, struct hist_entry, rb_node_in);
335 next = rb_next(&n->rb_node); 369 next = rb_next(&n->rb_node_in);
336 370
337 rb_erase(&n->rb_node, &hists->entries); 371 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits);
338 __hists__insert_output_entry(&tmp, n, min_callchain_hits);
339 hists__inc_nr_entries(hists, n); 372 hists__inc_nr_entries(hists, n);
340 } 373 }
374}
341 375
342 hists->entries = tmp; 376void hists__output_resort(struct hists *hists)
377{
378 return __hists__output_resort(hists, false);
379}
380
381void hists__output_resort_threaded(struct hists *hists)
382{
383 return __hists__output_resort(hists, true);
343} 384}
344 385
345static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) 386static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
@@ -1043,3 +1084,13 @@ size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
1043 1084
1044 return ret; 1085 return ret;
1045} 1086}
1087
1088void hists__init(struct hists *hists)
1089{
1090 memset(hists, 0, sizeof(*hists));
1091 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
1092 hists->entries_in = &hists->entries_in_array[0];
1093 hists->entries_collapsed = RB_ROOT;
1094 hists->entries = RB_ROOT;
1095 pthread_mutex_init(&hists->lock, NULL);
1096}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 861ffc31db96..d3f976cc7c56 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -2,6 +2,7 @@
2#define __PERF_HIST_H 2#define __PERF_HIST_H
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <pthread.h>
5#include "callchain.h" 6#include "callchain.h"
6 7
7extern struct callchain_param callchain_param; 8extern struct callchain_param callchain_param;
@@ -43,8 +44,12 @@ enum hist_column {
43}; 44};
44 45
45struct hists { 46struct hists {
47 struct rb_root entries_in_array[2];
48 struct rb_root *entries_in;
46 struct rb_root entries; 49 struct rb_root entries;
50 struct rb_root entries_collapsed;
47 u64 nr_entries; 51 u64 nr_entries;
52 pthread_mutex_t lock;
48 struct events_stats stats; 53 struct events_stats stats;
49 u64 event_stream; 54 u64 event_stream;
50 u16 col_len[HISTC_NR_COLS]; 55 u16 col_len[HISTC_NR_COLS];
@@ -52,6 +57,8 @@ struct hists {
52 struct callchain_cursor callchain_cursor; 57 struct callchain_cursor callchain_cursor;
53}; 58};
54 59
60void hists__init(struct hists *hists);
61
55struct hist_entry *__hists__add_entry(struct hists *self, 62struct hist_entry *__hists__add_entry(struct hists *self,
56 struct addr_location *al, 63 struct addr_location *al,
57 struct symbol *parent, u64 period); 64 struct symbol *parent, u64 period);
@@ -67,7 +74,9 @@ int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size,
67void hist_entry__free(struct hist_entry *); 74void hist_entry__free(struct hist_entry *);
68 75
69void hists__output_resort(struct hists *self); 76void hists__output_resort(struct hists *self);
77void hists__output_resort_threaded(struct hists *hists);
70void hists__collapse_resort(struct hists *self); 78void hists__collapse_resort(struct hists *self);
79void hists__collapse_resort_threaded(struct hists *hists);
71 80
72void hists__inc_nr_events(struct hists *self, u32 type); 81void hists__inc_nr_events(struct hists *self, u32 type);
73size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); 82size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 77d0388ad415..03851e301721 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -45,6 +45,7 @@ extern enum sort_type sort__first_dimension;
45 * @nr_rows - rows expanded in callchain, recalculated on folding/unfolding 45 * @nr_rows - rows expanded in callchain, recalculated on folding/unfolding
46 */ 46 */
47struct hist_entry { 47struct hist_entry {
48 struct rb_node rb_node_in;
48 struct rb_node rb_node; 49 struct rb_node rb_node;
49 u64 period; 50 u64 period;
50 u64 period_sys; 51 u64 period_sys;