aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2014-01-13 21:52:48 -0500
committerJiri Olsa <jolsa@redhat.com>2014-04-16 11:16:03 -0400
commitf2148330544a697481219b5bc34261f6dd049bfb (patch)
treeb08733dad6f875401f8751e7f7402443372d28eb /tools
parent1ab1fa5dfb429c533fbc791e524788cf0cc43775 (diff)
perf report: Add --percentage option
The --percentage option is for controlling overhead percentage displayed. It can only receive either of "relative" or "absolute". "relative" means it's relative to filtered entries only so that the sum of shown entries will be always 100%. "absolute" means it retains the original value before and after the filter is applied. $ perf report -s comm # Overhead Command # ........ ............ # 74.19% cc1 7.61% gcc 6.11% as 4.35% sh 4.14% make 1.13% fixdep ... $ perf report -s comm -c cc1,gcc --percentage absolute # Overhead Command # ........ ............ # 74.19% cc1 7.61% gcc $ perf report -s comm -c cc1,gcc --percentage relative # Overhead Command # ........ ............ # 90.69% cc1 9.31% gcc Note that it has zero effect if no filter was applied. Suggested-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: Namhyung Kim <namhyung@kernel.org> Link: http://lkml.kernel.org/r/1397145720-8063-3-git-send-email-namhyung@kernel.org Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-report.txt24
-rw-r--r--tools/perf/builtin-report.c30
-rw-r--r--tools/perf/ui/browsers/hists.c35
-rw-r--r--tools/perf/ui/gtk/hists.c11
-rw-r--r--tools/perf/ui/hist.c8
-rw-r--r--tools/perf/util/hist.c39
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/symbol.c1
-rw-r--r--tools/perf/util/symbol.h3
9 files changed, 106 insertions, 46 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 8eab8a4bdeb8..09af66298564 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -25,10 +25,6 @@ OPTIONS
25--verbose:: 25--verbose::
26 Be more verbose. (show symbol address, etc) 26 Be more verbose. (show symbol address, etc)
27 27
28-d::
29--dsos=::
30 Only consider symbols in these dsos. CSV that understands
31 file://filename entries.
32-n:: 28-n::
33--show-nr-samples:: 29--show-nr-samples::
34 Show the number of samples for each symbol 30 Show the number of samples for each symbol
@@ -42,11 +38,18 @@ OPTIONS
42-c:: 38-c::
43--comms=:: 39--comms=::
44 Only consider symbols in these comms. CSV that understands 40 Only consider symbols in these comms. CSV that understands
45 file://filename entries. 41 file://filename entries. This option will affect the percentage of
42 the overhead column. See --percentage for more info.
43-d::
44--dsos=::
45 Only consider symbols in these dsos. CSV that understands
46 file://filename entries. This option will affect the percentage of
47 the overhead column. See --percentage for more info.
46-S:: 48-S::
47--symbols=:: 49--symbols=::
48 Only consider these symbols. CSV that understands 50 Only consider these symbols. CSV that understands
49 file://filename entries. 51 file://filename entries. This option will affect the percentage of
52 the overhead column. See --percentage for more info.
50 53
51--symbol-filter=:: 54--symbol-filter=::
52 Only show symbols that match (partially) with this filter. 55 Only show symbols that match (partially) with this filter.
@@ -237,6 +240,15 @@ OPTIONS
237 Do not show entries which have an overhead under that percent. 240 Do not show entries which have an overhead under that percent.
238 (Default: 0). 241 (Default: 0).
239 242
243--percentage::
244 Determine how to display the overhead percentage of filtered entries.
245 Filters can be applied by --comms, --dsos and/or --symbols options and
246 Zoom operations on the TUI (thread, dso, etc).
247
248 "relative" means it's relative to filtered entries only so that the
249 sum of shown entries will be always 100%. "absolute" means it retains
250 the original value before and after the filter is applied.
251
240--header:: 252--header::
241 Show header information in the perf.data file. This includes 253 Show header information in the perf.data file. This includes
242 various information like hostname, OS and perf version, cpu/mem 254 various information like hostname, OS and perf version, cpu/mem
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2fca56c9d68a..7ec351bda833 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -343,6 +343,11 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
343 char buf[512]; 343 char buf[512];
344 size_t size = sizeof(buf); 344 size_t size = sizeof(buf);
345 345
346 if (symbol_conf.filter_relative) {
347 nr_samples = hists->stats.nr_non_filtered_samples;
348 nr_events = hists->stats.total_non_filtered_period;
349 }
350
346 if (perf_evsel__is_group_event(evsel)) { 351 if (perf_evsel__is_group_event(evsel)) {
347 struct perf_evsel *pos; 352 struct perf_evsel *pos;
348 353
@@ -350,8 +355,13 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
350 evname = buf; 355 evname = buf;
351 356
352 for_each_group_member(pos, evsel) { 357 for_each_group_member(pos, evsel) {
353 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 358 if (symbol_conf.filter_relative) {
354 nr_events += pos->hists.stats.total_period; 359 nr_samples += pos->hists.stats.nr_non_filtered_samples;
360 nr_events += pos->hists.stats.total_non_filtered_period;
361 } else {
362 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
363 nr_events += pos->hists.stats.total_period;
364 }
355 } 365 }
356 } 366 }
357 367
@@ -707,6 +717,20 @@ parse_percent_limit(const struct option *opt, const char *str,
707 return 0; 717 return 0;
708} 718}
709 719
720static int
721parse_percentage(const struct option *opt __maybe_unused, const char *str,
722 int unset __maybe_unused)
723{
724 if (!strcmp(str, "relative"))
725 symbol_conf.filter_relative = true;
726 else if (!strcmp(str, "absolute"))
727 symbol_conf.filter_relative = false;
728 else
729 return -1;
730
731 return 0;
732}
733
710int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) 734int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
711{ 735{
712 struct perf_session *session; 736 struct perf_session *session;
@@ -829,6 +853,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
829 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 853 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
830 OPT_CALLBACK(0, "percent-limit", &report, "percent", 854 OPT_CALLBACK(0, "percent-limit", &report, "percent",
831 "Don't show entries under that percent", parse_percent_limit), 855 "Don't show entries under that percent", parse_percent_limit),
856 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
857 "how to display percentage of filtered entries", parse_percentage),
832 OPT_END() 858 OPT_END()
833 }; 859 };
834 struct perf_data_file file = { 860 struct perf_data_file file = {
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 7ec871af3f6f..7ad11477a0f5 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -769,12 +769,15 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
769 769
770 for (nd = browser->top; nd; nd = rb_next(nd)) { 770 for (nd = browser->top; nd; nd = rb_next(nd)) {
771 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 771 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
772 float percent = h->stat.period * 100.0 / 772 u64 total = hists__total_period(h->hists);
773 hb->hists->stats.total_period; 773 float percent = 0.0;
774 774
775 if (h->filtered) 775 if (h->filtered)
776 continue; 776 continue;
777 777
778 if (total)
779 percent = h->stat.period * 100.0 / total;
780
778 if (percent < hb->min_pcnt) 781 if (percent < hb->min_pcnt)
779 continue; 782 continue;
780 783
@@ -792,8 +795,11 @@ static struct rb_node *hists__filter_entries(struct rb_node *nd,
792{ 795{
793 while (nd != NULL) { 796 while (nd != NULL) {
794 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 797 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
795 float percent = h->stat.period * 100.0 / 798 u64 total = hists__total_period(hists);
796 hists->stats.total_period; 799 float percent = 0.0;
800
801 if (total)
802 percent = h->stat.period * 100.0 / total;
797 803
798 if (percent < min_pcnt) 804 if (percent < min_pcnt)
799 return NULL; 805 return NULL;
@@ -813,8 +819,11 @@ static struct rb_node *hists__filter_prev_entries(struct rb_node *nd,
813{ 819{
814 while (nd != NULL) { 820 while (nd != NULL) {
815 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 821 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
816 float percent = h->stat.period * 100.0 / 822 u64 total = hists__total_period(hists);
817 hists->stats.total_period; 823 float percent = 0.0;
824
825 if (total)
826 percent = h->stat.period * 100.0 / total;
818 827
819 if (!h->filtered && percent >= min_pcnt) 828 if (!h->filtered && percent >= min_pcnt)
820 return nd; 829 return nd;
@@ -1189,6 +1198,11 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
1189 char buf[512]; 1198 char buf[512];
1190 size_t buflen = sizeof(buf); 1199 size_t buflen = sizeof(buf);
1191 1200
1201 if (symbol_conf.filter_relative) {
1202 nr_samples = hists->stats.nr_non_filtered_samples;
1203 nr_events = hists->stats.total_non_filtered_period;
1204 }
1205
1192 if (perf_evsel__is_group_event(evsel)) { 1206 if (perf_evsel__is_group_event(evsel)) {
1193 struct perf_evsel *pos; 1207 struct perf_evsel *pos;
1194 1208
@@ -1196,8 +1210,13 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
1196 ev_name = buf; 1210 ev_name = buf;
1197 1211
1198 for_each_group_member(pos, evsel) { 1212 for_each_group_member(pos, evsel) {
1199 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1213 if (symbol_conf.filter_relative) {
1200 nr_events += pos->hists.stats.total_period; 1214 nr_samples += pos->hists.stats.nr_non_filtered_samples;
1215 nr_events += pos->hists.stats.total_non_filtered_period;
1216 } else {
1217 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
1218 nr_events += pos->hists.stats.total_period;
1219 }
1201 } 1220 }
1202 } 1221 }
1203 1222
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index e395ef9b0ae0..91f10f3f6dd1 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -228,12 +228,15 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
228 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 228 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
229 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 229 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
230 GtkTreeIter iter; 230 GtkTreeIter iter;
231 float percent = h->stat.period * 100.0 / 231 u64 total = hists__total_period(h->hists);
232 hists->stats.total_period; 232 float percent = 0.0;
233 233
234 if (h->filtered) 234 if (h->filtered)
235 continue; 235 continue;
236 236
237 if (total)
238 percent = h->stat.period * 100.0 / total;
239
237 if (percent < min_pcnt) 240 if (percent < min_pcnt)
238 continue; 241 continue;
239 242
@@ -261,12 +264,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
261 } 264 }
262 265
263 if (symbol_conf.use_callchain && sort__has_sym) { 266 if (symbol_conf.use_callchain && sort__has_sym) {
264 u64 total;
265
266 if (callchain_param.mode == CHAIN_GRAPH_REL) 267 if (callchain_param.mode == CHAIN_GRAPH_REL)
267 total = h->stat.period; 268 total = h->stat.period;
268 else
269 total = hists->stats.total_period;
270 269
271 perf_gtk__add_callchain(&h->sorted_chain, store, &iter, 270 perf_gtk__add_callchain(&h->sorted_chain, store, &iter,
272 sym_col, total); 271 sym_col, total);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 0f403b83e9d1..0912805c08f4 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -32,10 +32,10 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
32 32
33 if (fmt_percent) { 33 if (fmt_percent) {
34 double percent = 0.0; 34 double percent = 0.0;
35 u64 total = hists__total_period(hists);
35 36
36 if (hists->stats.total_period) 37 if (total)
37 percent = 100.0 * get_field(he) / 38 percent = 100.0 * get_field(he) / total;
38 hists->stats.total_period;
39 39
40 ret += hpp__call_print_fn(hpp, print_fn, fmt, percent); 40 ret += hpp__call_print_fn(hpp, print_fn, fmt, percent);
41 } else 41 } else
@@ -50,7 +50,7 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
50 50
51 list_for_each_entry(pair, &he->pairs.head, pairs.node) { 51 list_for_each_entry(pair, &he->pairs.head, pairs.node) {
52 u64 period = get_field(pair); 52 u64 period = get_field(pair);
53 u64 total = pair->hists->stats.total_period; 53 u64 total = hists__total_period(pair->hists);
54 54
55 if (!total) 55 if (!total)
56 continue; 56 continue;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 1ed3e2b86f0b..3ebd89a28257 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -321,9 +321,11 @@ void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
321{ 321{
322 if (!h->filtered) { 322 if (!h->filtered) {
323 hists__calc_col_len(hists, h); 323 hists__calc_col_len(hists, h);
324 ++hists->nr_entries; 324 hists->nr_non_filtered_entries++;
325 hists->stats.total_period += h->stat.period; 325 hists->stats.total_non_filtered_period += h->stat.period;
326 } 326 }
327 hists->nr_entries++;
328 hists->stats.total_period += h->stat.period;
327} 329}
328 330
329static u8 symbol__parent_filter(const struct symbol *parent) 331static u8 symbol__parent_filter(const struct symbol *parent)
@@ -674,8 +676,9 @@ void hists__output_resort(struct hists *hists)
674 next = rb_first(root); 676 next = rb_first(root);
675 hists->entries = RB_ROOT; 677 hists->entries = RB_ROOT;
676 678
677 hists->nr_entries = hists->nr_non_filtered_entries = 0; 679 hists->nr_non_filtered_entries = 0;
678 hists->stats.total_period = hists->stats.total_non_filtered_period = 0; 680 hists->stats.total_period = 0;
681 hists->stats.total_non_filtered_period = 0;
679 hists__reset_col_len(hists); 682 hists__reset_col_len(hists);
680 683
681 while (next) { 684 while (next) {
@@ -694,16 +697,11 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
694 if (h->filtered) 697 if (h->filtered)
695 return; 698 return;
696 699
697 ++hists->nr_entries;
698 ++hists->nr_non_filtered_entries; 700 ++hists->nr_non_filtered_entries;
699 if (h->ms.unfolded) { 701 if (h->ms.unfolded)
700 hists->nr_entries += h->nr_rows;
701 hists->nr_non_filtered_entries += h->nr_rows; 702 hists->nr_non_filtered_entries += h->nr_rows;
702 }
703 h->row_offset = 0; 703 h->row_offset = 0;
704 hists->stats.total_period += h->stat.period;
705 hists->stats.total_non_filtered_period += h->stat.period; 704 hists->stats.total_non_filtered_period += h->stat.period;
706 hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
707 hists->stats.nr_non_filtered_samples += h->stat.nr_events; 705 hists->stats.nr_non_filtered_samples += h->stat.nr_events;
708 706
709 hists__calc_col_len(hists, h); 707 hists__calc_col_len(hists, h);
@@ -726,9 +724,8 @@ void hists__filter_by_dso(struct hists *hists)
726{ 724{
727 struct rb_node *nd; 725 struct rb_node *nd;
728 726
729 hists->nr_entries = hists->stats.total_period = 0; 727 hists->nr_non_filtered_entries = 0;
730 hists->nr_non_filtered_entries = hists->stats.total_non_filtered_period = 0; 728 hists->stats.total_non_filtered_period = 0;
731 hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
732 hists->stats.nr_non_filtered_samples = 0; 729 hists->stats.nr_non_filtered_samples = 0;
733 hists__reset_col_len(hists); 730 hists__reset_col_len(hists);
734 731
@@ -761,9 +758,8 @@ void hists__filter_by_thread(struct hists *hists)
761{ 758{
762 struct rb_node *nd; 759 struct rb_node *nd;
763 760
764 hists->nr_entries = hists->stats.total_period = 0; 761 hists->nr_non_filtered_entries = 0;
765 hists->nr_non_filtered_entries = hists->stats.total_non_filtered_period = 0; 762 hists->stats.total_non_filtered_period = 0;
766 hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
767 hists->stats.nr_non_filtered_samples = 0; 763 hists->stats.nr_non_filtered_samples = 0;
768 hists__reset_col_len(hists); 764 hists__reset_col_len(hists);
769 765
@@ -794,9 +790,8 @@ void hists__filter_by_symbol(struct hists *hists)
794{ 790{
795 struct rb_node *nd; 791 struct rb_node *nd;
796 792
797 hists->nr_entries = hists->stats.total_period = 0; 793 hists->nr_non_filtered_entries = 0;
798 hists->nr_non_filtered_entries = hists->stats.total_non_filtered_period = 0; 794 hists->stats.total_non_filtered_period = 0;
799 hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
800 hists->stats.nr_non_filtered_samples = 0; 795 hists->stats.nr_non_filtered_samples = 0;
801 hists__reset_col_len(hists); 796 hists__reset_col_len(hists);
802 797
@@ -942,3 +937,9 @@ int hists__link(struct hists *leader, struct hists *other)
942 937
943 return 0; 938 return 0;
944} 939}
940
941u64 hists__total_period(struct hists *hists)
942{
943 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
944 hists->stats.total_period;
945}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 213551469f36..3191496bd3b7 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -115,6 +115,7 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
115void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 115void 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);
118void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); 119void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h);
119void hists__inc_nr_events(struct hists *hists, u32 type); 120void hists__inc_nr_events(struct hists *hists, u32 type);
120void events_stats__inc(struct events_stats *stats, u32 type); 121void events_stats__inc(struct events_stats *stats, u32 type);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 95e249779931..b2eca6c17a70 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -33,6 +33,7 @@ struct symbol_conf symbol_conf = {
33 .try_vmlinux_path = true, 33 .try_vmlinux_path = true,
34 .annotate_src = true, 34 .annotate_src = true,
35 .demangle = true, 35 .demangle = true,
36 .filter_relative = true,
36 .symfs = "", 37 .symfs = "",
37}; 38};
38 39
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 501e4e722e8e..ae94e006a52d 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -115,7 +115,8 @@ struct symbol_conf {
115 annotate_asm_raw, 115 annotate_asm_raw,
116 annotate_src, 116 annotate_src,
117 event_group, 117 event_group,
118 demangle; 118 demangle,
119 filter_relative;
119 const char *vmlinux_name, 120 const char *vmlinux_name,
120 *kallsyms_name, 121 *kallsyms_name,
121 *source_prefix, 122 *source_prefix,