aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-04-25 04:04:46 -0400
committerIngo Molnar <mingo@kernel.org>2014-04-25 04:04:46 -0400
commit2933d7813d8618f18632a7dc7f4e7f1f7d17383a (patch)
treedd178b76789c1d798c3aca230beaa7fac6872dcb
parent42ebd27bcbda7895fa07c61185a26d8379945ed0 (diff)
parentc3b789527b236873557f53740ceac47747e0e1cb (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core
Pull perf/core improvements and fixes from Jiri Olsa: * Factor hists statistics counts processing which in turn also fixes several bugs in TUI report command (Namhyung Kim) Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/builtin-annotate.c3
-rw-r--r--tools/perf/builtin-diff.c23
-rw-r--r--tools/perf/builtin-report.c64
-rw-r--r--tools/perf/ui/browsers/hists.c92
-rw-r--r--tools/perf/util/hist.c83
-rw-r--r--tools/perf/util/hist.h9
6 files changed, 171 insertions, 103 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 0da603b79b61..d30d2c2e2a7a 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -46,7 +46,7 @@ struct perf_annotate {
46}; 46};
47 47
48static int perf_evsel__add_sample(struct perf_evsel *evsel, 48static int perf_evsel__add_sample(struct perf_evsel *evsel,
49 struct perf_sample *sample, 49 struct perf_sample *sample __maybe_unused,
50 struct addr_location *al, 50 struct addr_location *al,
51 struct perf_annotate *ann) 51 struct perf_annotate *ann)
52{ 52{
@@ -70,7 +70,6 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
70 return -ENOMEM; 70 return -ENOMEM;
71 71
72 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 72 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
73 evsel->hists.stats.total_period += sample->period;
74 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 73 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
75 return ret; 74 return ret;
76} 75}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 6ef80f22c1e2..f3b10dcf6838 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -341,11 +341,16 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
341 return -1; 341 return -1;
342 } 342 }
343 343
344 if (al.filtered == 0) { 344 /*
345 evsel->hists.stats.total_non_filtered_period += sample->period; 345 * The total_period is updated here before going to the output
346 evsel->hists.nr_non_filtered_entries++; 346 * tree since normally only the baseline hists will call
347 } 347 * hists__output_resort() and precompute needs the total
348 * period in order to sort entries by percentage delta.
349 */
348 evsel->hists.stats.total_period += sample->period; 350 evsel->hists.stats.total_period += sample->period;
351 if (!al.filtered)
352 evsel->hists.stats.total_non_filtered_period += sample->period;
353
349 return 0; 354 return 0;
350} 355}
351 356
@@ -573,10 +578,7 @@ static void hists__compute_resort(struct hists *hists)
573 hists->entries = RB_ROOT; 578 hists->entries = RB_ROOT;
574 next = rb_first(root); 579 next = rb_first(root);
575 580
576 hists->nr_entries = 0; 581 hists__reset_stats(hists);
577 hists->nr_non_filtered_entries = 0;
578 hists->stats.total_period = 0;
579 hists->stats.total_non_filtered_period = 0;
580 hists__reset_col_len(hists); 582 hists__reset_col_len(hists);
581 583
582 while (next != NULL) { 584 while (next != NULL) {
@@ -586,7 +588,10 @@ static void hists__compute_resort(struct hists *hists)
586 next = rb_next(&he->rb_node_in); 588 next = rb_next(&he->rb_node_in);
587 589
588 insert_hist_entry_by_compute(&hists->entries, he, compute); 590 insert_hist_entry_by_compute(&hists->entries, he, compute);
589 hists__inc_nr_entries(hists, he); 591 hists__inc_stats(hists, he);
592
593 if (!he->filtered)
594 hists__calc_col_len(hists, he);
590 } 595 }
591} 596}
592 597
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 76e2bb6cf571..89c95289fd51 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -57,6 +57,7 @@ struct report {
57 const char *cpu_list; 57 const char *cpu_list;
58 const char *symbol_filter_str; 58 const char *symbol_filter_str;
59 float min_percent; 59 float min_percent;
60 u64 nr_entries;
60 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 61 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
61}; 62};
62 63
@@ -75,6 +76,27 @@ static int report__config(const char *var, const char *value, void *cb)
75 return perf_default_config(var, value, cb); 76 return perf_default_config(var, value, cb);
76} 77}
77 78
79static void report__inc_stats(struct report *rep, struct hist_entry *he)
80{
81 /*
82 * The @he is either of a newly created one or an existing one
83 * merging current sample. We only want to count a new one so
84 * checking ->nr_events being 1.
85 */
86 if (he->stat.nr_events == 1)
87 rep->nr_entries++;
88
89 /*
90 * Only counts number of samples at this stage as it's more
91 * natural to do it here and non-sample events are also
92 * counted in perf_session_deliver_event(). The dump_trace
93 * requires this info is ready before going to the output tree.
94 */
95 hists__inc_nr_events(he->hists, PERF_RECORD_SAMPLE);
96 if (!he->filtered)
97 he->hists->stats.nr_non_filtered_samples++;
98}
99
78static int report__add_mem_hist_entry(struct report *rep, struct addr_location *al, 100static int report__add_mem_hist_entry(struct report *rep, struct addr_location *al,
79 struct perf_sample *sample, struct perf_evsel *evsel) 101 struct perf_sample *sample, struct perf_evsel *evsel)
80{ 102{
@@ -121,10 +143,8 @@ static int report__add_mem_hist_entry(struct report *rep, struct addr_location *
121 goto out; 143 goto out;
122 } 144 }
123 145
124 evsel->hists.stats.total_period += cost; 146 report__inc_stats(rep, he);
125 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 147
126 if (!he->filtered)
127 evsel->hists.stats.nr_non_filtered_samples++;
128 err = hist_entry__append_callchain(he, sample); 148 err = hist_entry__append_callchain(he, sample);
129out: 149out:
130 return err; 150 return err;
@@ -175,11 +195,7 @@ static int report__add_branch_hist_entry(struct report *rep, struct addr_locatio
175 if (err) 195 if (err)
176 goto out; 196 goto out;
177 } 197 }
178 198 report__inc_stats(rep, he);
179 evsel->hists.stats.total_period += 1;
180 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
181 if (!he->filtered)
182 evsel->hists.stats.nr_non_filtered_samples++;
183 } else 199 } else
184 goto out; 200 goto out;
185 } 201 }
@@ -212,10 +228,8 @@ static int report__add_hist_entry(struct report *rep, struct perf_evsel *evsel,
212 if (ui__has_annotation()) 228 if (ui__has_annotation())
213 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 229 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
214 230
215 evsel->hists.stats.total_period += sample->period; 231 report__inc_stats(rep, he);
216 if (!he->filtered) 232
217 evsel->hists.stats.nr_non_filtered_samples++;
218 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
219out: 233out:
220 return err; 234 return err;
221} 235}
@@ -486,24 +500,12 @@ static int report__browse_hists(struct report *rep)
486 return ret; 500 return ret;
487} 501}
488 502
489static u64 report__collapse_hists(struct report *rep) 503static void report__collapse_hists(struct report *rep)
490{ 504{
491 struct ui_progress prog; 505 struct ui_progress prog;
492 struct perf_evsel *pos; 506 struct perf_evsel *pos;
493 u64 nr_samples = 0;
494 /*
495 * Count number of histogram entries to use when showing progress,
496 * reusing nr_samples variable.
497 */
498 evlist__for_each(rep->session->evlist, pos)
499 nr_samples += pos->hists.nr_entries;
500 507
501 ui_progress__init(&prog, nr_samples, "Merging related events..."); 508 ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
502 /*
503 * Count total number of samples, will be used to check if this
504 * session had any.
505 */
506 nr_samples = 0;
507 509
508 evlist__for_each(rep->session->evlist, pos) { 510 evlist__for_each(rep->session->evlist, pos) {
509 struct hists *hists = &pos->hists; 511 struct hists *hists = &pos->hists;
@@ -512,7 +514,6 @@ static u64 report__collapse_hists(struct report *rep)
512 hists->symbol_filter_str = rep->symbol_filter_str; 514 hists->symbol_filter_str = rep->symbol_filter_str;
513 515
514 hists__collapse_resort(hists, &prog); 516 hists__collapse_resort(hists, &prog);
515 nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
516 517
517 /* Non-group events are considered as leader */ 518 /* Non-group events are considered as leader */
518 if (symbol_conf.event_group && 519 if (symbol_conf.event_group &&
@@ -525,14 +526,11 @@ static u64 report__collapse_hists(struct report *rep)
525 } 526 }
526 527
527 ui_progress__finish(); 528 ui_progress__finish();
528
529 return nr_samples;
530} 529}
531 530
532static int __cmd_report(struct report *rep) 531static int __cmd_report(struct report *rep)
533{ 532{
534 int ret; 533 int ret;
535 u64 nr_samples;
536 struct perf_session *session = rep->session; 534 struct perf_session *session = rep->session;
537 struct perf_evsel *pos; 535 struct perf_evsel *pos;
538 struct perf_data_file *file = session->file; 536 struct perf_data_file *file = session->file;
@@ -572,12 +570,12 @@ static int __cmd_report(struct report *rep)
572 } 570 }
573 } 571 }
574 572
575 nr_samples = report__collapse_hists(rep); 573 report__collapse_hists(rep);
576 574
577 if (session_done()) 575 if (session_done())
578 return 0; 576 return 0;
579 577
580 if (nr_samples == 0) { 578 if (rep->nr_entries == 0) {
581 ui__error("The %s file has no samples!\n", file->path); 579 ui__error("The %s file has no samples!\n", file->path);
582 return 0; 580 return 0;
583 } 581 }
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 4d416984c59d..b0861e3e50a5 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -26,13 +26,36 @@ struct hist_browser {
26 int print_seq; 26 int print_seq;
27 bool show_dso; 27 bool show_dso;
28 float min_pcnt; 28 float min_pcnt;
29 u64 nr_pcnt_entries; 29 u64 nr_non_filtered_entries;
30 u64 nr_callchain_rows;
30}; 31};
31 32
32extern void hist_browser__init_hpp(void); 33extern void hist_browser__init_hpp(void);
33 34
34static int hists__browser_title(struct hists *hists, char *bf, size_t size, 35static int hists__browser_title(struct hists *hists, char *bf, size_t size,
35 const char *ev_name); 36 const char *ev_name);
37static void hist_browser__update_nr_entries(struct hist_browser *hb);
38
39static struct rb_node *hists__filter_entries(struct rb_node *nd,
40 struct hists *hists,
41 float min_pcnt);
42
43static bool hist_browser__has_filter(struct hist_browser *hb)
44{
45 return hists__has_filter(hb->hists) || hb->min_pcnt;
46}
47
48static u32 hist_browser__nr_entries(struct hist_browser *hb)
49{
50 u32 nr_entries;
51
52 if (hist_browser__has_filter(hb))
53 nr_entries = hb->nr_non_filtered_entries;
54 else
55 nr_entries = hb->hists->nr_entries;
56
57 return nr_entries + hb->nr_callchain_rows;
58}
36 59
37static void hist_browser__refresh_dimensions(struct hist_browser *browser) 60static void hist_browser__refresh_dimensions(struct hist_browser *browser)
38{ 61{
@@ -43,7 +66,14 @@ static void hist_browser__refresh_dimensions(struct hist_browser *browser)
43 66
44static void hist_browser__reset(struct hist_browser *browser) 67static void hist_browser__reset(struct hist_browser *browser)
45{ 68{
46 browser->b.nr_entries = browser->hists->nr_entries; 69 /*
70 * The hists__remove_entry_filter() already folds non-filtered
71 * entries so we can assume it has 0 callchain rows.
72 */
73 browser->nr_callchain_rows = 0;
74
75 hist_browser__update_nr_entries(browser);
76 browser->b.nr_entries = hist_browser__nr_entries(browser);
47 hist_browser__refresh_dimensions(browser); 77 hist_browser__refresh_dimensions(browser);
48 ui_browser__reset_index(&browser->b); 78 ui_browser__reset_index(&browser->b);
49} 79}
@@ -198,14 +228,16 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser)
198 struct hist_entry *he = browser->he_selection; 228 struct hist_entry *he = browser->he_selection;
199 229
200 hist_entry__init_have_children(he); 230 hist_entry__init_have_children(he);
201 browser->hists->nr_entries -= he->nr_rows; 231 browser->b.nr_entries -= he->nr_rows;
232 browser->nr_callchain_rows -= he->nr_rows;
202 233
203 if (he->ms.unfolded) 234 if (he->ms.unfolded)
204 he->nr_rows = callchain__count_rows(&he->sorted_chain); 235 he->nr_rows = callchain__count_rows(&he->sorted_chain);
205 else 236 else
206 he->nr_rows = 0; 237 he->nr_rows = 0;
207 browser->hists->nr_entries += he->nr_rows; 238
208 browser->b.nr_entries = browser->hists->nr_entries; 239 browser->b.nr_entries += he->nr_rows;
240 browser->nr_callchain_rows += he->nr_rows;
209 241
210 return true; 242 return true;
211 } 243 }
@@ -280,23 +312,27 @@ static void hist_entry__set_folding(struct hist_entry *he, bool unfold)
280 he->nr_rows = 0; 312 he->nr_rows = 0;
281} 313}
282 314
283static void hists__set_folding(struct hists *hists, bool unfold) 315static void
316__hist_browser__set_folding(struct hist_browser *browser, bool unfold)
284{ 317{
285 struct rb_node *nd; 318 struct rb_node *nd;
319 struct hists *hists = browser->hists;
286 320
287 hists->nr_entries = 0; 321 for (nd = rb_first(&hists->entries);
288 322 (nd = hists__filter_entries(nd, hists, browser->min_pcnt)) != NULL;
289 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 323 nd = rb_next(nd)) {
290 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); 324 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
291 hist_entry__set_folding(he, unfold); 325 hist_entry__set_folding(he, unfold);
292 hists->nr_entries += 1 + he->nr_rows; 326 browser->nr_callchain_rows += he->nr_rows;
293 } 327 }
294} 328}
295 329
296static void hist_browser__set_folding(struct hist_browser *browser, bool unfold) 330static void hist_browser__set_folding(struct hist_browser *browser, bool unfold)
297{ 331{
298 hists__set_folding(browser->hists, unfold); 332 browser->nr_callchain_rows = 0;
299 browser->b.nr_entries = browser->hists->nr_entries; 333 __hist_browser__set_folding(browser, unfold);
334
335 browser->b.nr_entries = hist_browser__nr_entries(browser);
300 /* Go to the start, we may be way after valid entries after a collapse */ 336 /* Go to the start, we may be way after valid entries after a collapse */
301 ui_browser__reset_index(&browser->b); 337 ui_browser__reset_index(&browser->b);
302} 338}
@@ -310,8 +346,6 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
310 "Or reduce the sampling frequency."); 346 "Or reduce the sampling frequency.");
311} 347}
312 348
313static void hist_browser__update_pcnt_entries(struct hist_browser *hb);
314
315static int hist_browser__run(struct hist_browser *browser, const char *ev_name, 349static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
316 struct hist_browser_timer *hbt) 350 struct hist_browser_timer *hbt)
317{ 351{
@@ -320,9 +354,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
320 int delay_secs = hbt ? hbt->refresh : 0; 354 int delay_secs = hbt ? hbt->refresh : 0;
321 355
322 browser->b.entries = &browser->hists->entries; 356 browser->b.entries = &browser->hists->entries;
323 browser->b.nr_entries = browser->hists->nr_entries; 357 browser->b.nr_entries = hist_browser__nr_entries(browser);
324 if (browser->min_pcnt)
325 browser->b.nr_entries = browser->nr_pcnt_entries;
326 358
327 hist_browser__refresh_dimensions(browser); 359 hist_browser__refresh_dimensions(browser);
328 hists__browser_title(browser->hists, title, sizeof(title), ev_name); 360 hists__browser_title(browser->hists, title, sizeof(title), ev_name);
@@ -339,13 +371,10 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
339 u64 nr_entries; 371 u64 nr_entries;
340 hbt->timer(hbt->arg); 372 hbt->timer(hbt->arg);
341 373
342 if (browser->min_pcnt) { 374 if (hist_browser__has_filter(browser))
343 hist_browser__update_pcnt_entries(browser); 375 hist_browser__update_nr_entries(browser);
344 nr_entries = browser->nr_pcnt_entries;
345 } else {
346 nr_entries = browser->hists->nr_entries;
347 }
348 376
377 nr_entries = hist_browser__nr_entries(browser);
349 ui_browser__update_nr_entries(&browser->b, nr_entries); 378 ui_browser__update_nr_entries(&browser->b, nr_entries);
350 379
351 if (browser->hists->stats.nr_lost_warned != 380 if (browser->hists->stats.nr_lost_warned !=
@@ -1343,18 +1372,23 @@ close_file_and_continue:
1343 return ret; 1372 return ret;
1344} 1373}
1345 1374
1346static void hist_browser__update_pcnt_entries(struct hist_browser *hb) 1375static void hist_browser__update_nr_entries(struct hist_browser *hb)
1347{ 1376{
1348 u64 nr_entries = 0; 1377 u64 nr_entries = 0;
1349 struct rb_node *nd = rb_first(&hb->hists->entries); 1378 struct rb_node *nd = rb_first(&hb->hists->entries);
1350 1379
1351 while (nd) { 1380 if (hb->min_pcnt == 0) {
1381 hb->nr_non_filtered_entries = hb->hists->nr_non_filtered_entries;
1382 return;
1383 }
1384
1385 while ((nd = hists__filter_entries(nd, hb->hists,
1386 hb->min_pcnt)) != NULL) {
1352 nr_entries++; 1387 nr_entries++;
1353 nd = hists__filter_entries(rb_next(nd), hb->hists, 1388 nd = rb_next(nd);
1354 hb->min_pcnt);
1355 } 1389 }
1356 1390
1357 hb->nr_pcnt_entries = nr_entries; 1391 hb->nr_non_filtered_entries = nr_entries;
1358} 1392}
1359 1393
1360static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, 1394static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
@@ -1411,7 +1445,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1411 1445
1412 if (min_pcnt) { 1446 if (min_pcnt) {
1413 browser->min_pcnt = min_pcnt; 1447 browser->min_pcnt = min_pcnt;
1414 hist_browser__update_pcnt_entries(browser); 1448 hist_browser__update_nr_entries(browser);
1415 } 1449 }
1416 1450
1417 fstack = pstack__new(2); 1451 fstack = pstack__new(2);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 5a892477aa50..7f0236cea4fe 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -225,14 +225,18 @@ static void he_stat__decay(struct he_stat *he_stat)
225static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) 225static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
226{ 226{
227 u64 prev_period = he->stat.period; 227 u64 prev_period = he->stat.period;
228 u64 diff;
228 229
229 if (prev_period == 0) 230 if (prev_period == 0)
230 return true; 231 return true;
231 232
232 he_stat__decay(&he->stat); 233 he_stat__decay(&he->stat);
233 234
235 diff = prev_period - he->stat.period;
236
237 hists->stats.total_period -= diff;
234 if (!he->filtered) 238 if (!he->filtered)
235 hists->stats.total_period -= prev_period - he->stat.period; 239 hists->stats.total_non_filtered_period -= diff;
236 240
237 return he->stat.period == 0; 241 return he->stat.period == 0;
238} 242}
@@ -259,8 +263,11 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
259 if (sort__need_collapse) 263 if (sort__need_collapse)
260 rb_erase(&n->rb_node_in, &hists->entries_collapsed); 264 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
261 265
262 hist_entry__free(n);
263 --hists->nr_entries; 266 --hists->nr_entries;
267 if (!n->filtered)
268 --hists->nr_non_filtered_entries;
269
270 hist_entry__free(n);
264 } 271 }
265 } 272 }
266} 273}
@@ -317,17 +324,6 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
317 return he; 324 return he;
318} 325}
319 326
320void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
321{
322 if (!h->filtered) {
323 hists__calc_col_len(hists, h);
324 hists->nr_non_filtered_entries++;
325 hists->stats.total_non_filtered_period += h->stat.period;
326 }
327 hists->nr_entries++;
328 hists->stats.total_period += h->stat.period;
329}
330
331static u8 symbol__parent_filter(const struct symbol *parent) 327static u8 symbol__parent_filter(const struct symbol *parent)
332{ 328{
333 if (symbol_conf.exclude_other && parent == NULL) 329 if (symbol_conf.exclude_other && parent == NULL)
@@ -393,7 +389,6 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
393 if (!he) 389 if (!he)
394 return NULL; 390 return NULL;
395 391
396 hists->nr_entries++;
397 rb_link_node(&he->rb_node_in, parent, p); 392 rb_link_node(&he->rb_node_in, parent, p);
398 rb_insert_color(&he->rb_node_in, hists->entries_in); 393 rb_insert_color(&he->rb_node_in, hists->entries_in);
399out: 394out:
@@ -633,6 +628,35 @@ out:
633 return ret; 628 return ret;
634} 629}
635 630
631static void hists__reset_filter_stats(struct hists *hists)
632{
633 hists->nr_non_filtered_entries = 0;
634 hists->stats.total_non_filtered_period = 0;
635}
636
637void hists__reset_stats(struct hists *hists)
638{
639 hists->nr_entries = 0;
640 hists->stats.total_period = 0;
641
642 hists__reset_filter_stats(hists);
643}
644
645static void hists__inc_filter_stats(struct hists *hists, struct hist_entry *h)
646{
647 hists->nr_non_filtered_entries++;
648 hists->stats.total_non_filtered_period += h->stat.period;
649}
650
651void hists__inc_stats(struct hists *hists, struct hist_entry *h)
652{
653 if (!h->filtered)
654 hists__inc_filter_stats(hists, h);
655
656 hists->nr_entries++;
657 hists->stats.total_period += h->stat.period;
658}
659
636static void __hists__insert_output_entry(struct rb_root *entries, 660static void __hists__insert_output_entry(struct rb_root *entries,
637 struct hist_entry *he, 661 struct hist_entry *he,
638 u64 min_callchain_hits) 662 u64 min_callchain_hits)
@@ -676,9 +700,7 @@ void hists__output_resort(struct hists *hists)
676 next = rb_first(root); 700 next = rb_first(root);
677 hists->entries = RB_ROOT; 701 hists->entries = RB_ROOT;
678 702
679 hists->nr_non_filtered_entries = 0; 703 hists__reset_stats(hists);
680 hists->stats.total_period = 0;
681 hists->stats.total_non_filtered_period = 0;
682 hists__reset_col_len(hists); 704 hists__reset_col_len(hists);
683 705
684 while (next) { 706 while (next) {
@@ -686,7 +708,10 @@ void hists__output_resort(struct hists *hists)
686 next = rb_next(&n->rb_node_in); 708 next = rb_next(&n->rb_node_in);
687 709
688 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits); 710 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits);
689 hists__inc_nr_entries(hists, n); 711 hists__inc_stats(hists, n);
712
713 if (!n->filtered)
714 hists__calc_col_len(hists, n);
690 } 715 }
691} 716}
692 717
@@ -697,13 +722,13 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
697 if (h->filtered) 722 if (h->filtered)
698 return; 723 return;
699 724
700 ++hists->nr_non_filtered_entries; 725 /* force fold unfiltered entry for simplicity */
701 if (h->ms.unfolded) 726 h->ms.unfolded = false;
702 hists->nr_non_filtered_entries += h->nr_rows;
703 h->row_offset = 0; 727 h->row_offset = 0;
704 hists->stats.total_non_filtered_period += h->stat.period; 728
705 hists->stats.nr_non_filtered_samples += h->stat.nr_events; 729 hists->stats.nr_non_filtered_samples += h->stat.nr_events;
706 730
731 hists__inc_filter_stats(hists, h);
707 hists__calc_col_len(hists, h); 732 hists__calc_col_len(hists, h);
708} 733}
709 734
@@ -724,9 +749,9 @@ void hists__filter_by_dso(struct hists *hists)
724{ 749{
725 struct rb_node *nd; 750 struct rb_node *nd;
726 751
727 hists->nr_non_filtered_entries = 0;
728 hists->stats.total_non_filtered_period = 0;
729 hists->stats.nr_non_filtered_samples = 0; 752 hists->stats.nr_non_filtered_samples = 0;
753
754 hists__reset_filter_stats(hists);
730 hists__reset_col_len(hists); 755 hists__reset_col_len(hists);
731 756
732 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 757 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
@@ -758,9 +783,9 @@ void hists__filter_by_thread(struct hists *hists)
758{ 783{
759 struct rb_node *nd; 784 struct rb_node *nd;
760 785
761 hists->nr_non_filtered_entries = 0;
762 hists->stats.total_non_filtered_period = 0;
763 hists->stats.nr_non_filtered_samples = 0; 786 hists->stats.nr_non_filtered_samples = 0;
787
788 hists__reset_filter_stats(hists);
764 hists__reset_col_len(hists); 789 hists__reset_col_len(hists);
765 790
766 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 791 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
@@ -790,9 +815,9 @@ void hists__filter_by_symbol(struct hists *hists)
790{ 815{
791 struct rb_node *nd; 816 struct rb_node *nd;
792 817
793 hists->nr_non_filtered_entries = 0;
794 hists->stats.total_non_filtered_period = 0;
795 hists->stats.nr_non_filtered_samples = 0; 818 hists->stats.nr_non_filtered_samples = 0;
819
820 hists__reset_filter_stats(hists);
796 hists__reset_col_len(hists); 821 hists__reset_col_len(hists);
797 822
798 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 823 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
@@ -853,7 +878,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
853 he->hists = hists; 878 he->hists = hists;
854 rb_link_node(&he->rb_node_in, parent, p); 879 rb_link_node(&he->rb_node_in, parent, p);
855 rb_insert_color(&he->rb_node_in, root); 880 rb_insert_color(&he->rb_node_in, root);
856 hists__inc_nr_entries(hists, he); 881 hists__inc_stats(hists, he);
857 he->dummy = true; 882 he->dummy = true;
858 } 883 }
859out: 884out:
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 5a0343eb22e2..38c3e874c164 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -116,7 +116,8 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
116void hists__output_recalc_col_len(struct hists *hists, int max_rows); 116void hists__output_recalc_col_len(struct hists *hists, int max_rows);
117 117
118u64 hists__total_period(struct hists *hists); 118u64 hists__total_period(struct hists *hists);
119void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); 119void hists__reset_stats(struct hists *hists);
120void hists__inc_stats(struct hists *hists, struct hist_entry *h);
120void hists__inc_nr_events(struct hists *hists, u32 type); 121void hists__inc_nr_events(struct hists *hists, u32 type);
121void events_stats__inc(struct events_stats *stats, u32 type); 122void events_stats__inc(struct events_stats *stats, u32 type);
122size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); 123size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
@@ -128,6 +129,12 @@ void hists__filter_by_dso(struct hists *hists);
128void hists__filter_by_thread(struct hists *hists); 129void hists__filter_by_thread(struct hists *hists);
129void hists__filter_by_symbol(struct hists *hists); 130void hists__filter_by_symbol(struct hists *hists);
130 131
132static inline bool hists__has_filter(struct hists *hists)
133{
134 return hists->thread_filter || hists->dso_filter ||
135 hists->symbol_filter_str;
136}
137
131u16 hists__col_len(struct hists *hists, enum hist_column col); 138u16 hists__col_len(struct hists *hists, enum hist_column col);
132void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len); 139void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len);
133bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len); 140bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len);