diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-04-17 04:06:47 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-04-17 04:06:47 -0400 |
commit | b3d5fc3c297fd379956689dc4d7d6af077ac35c2 (patch) | |
tree | 2c0882061596156ef39e17360c442aef4a64c3b6 | |
parent | fbdd17ec5ce2e5e4027356fcfde769b88d15702f (diff) | |
parent | a83edb2dfc5989fbadc594109c933bae528a2809 (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:
User visible changes:
* Add --percentage option to control absolute/relative percentage output (Namhyung Kim)
Plumbing changes:
* Add --list-cmds to 'kmem', 'mem', 'lock' and 'sched', for use by completion scripts (Ramkumar Ramachandra)
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/perf/Documentation/perf-diff.txt | 21 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 24 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-top.txt | 18 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 32 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 8 | ||||
-rw-r--r-- | tools/perf/builtin-lock.c | 10 | ||||
-rw-r--r-- | tools/perf/builtin-mem.c | 15 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 22 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 10 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 8 | ||||
-rw-r--r-- | tools/perf/perf-completion.sh | 4 | ||||
-rw-r--r-- | tools/perf/ui/browsers/hists.c | 39 | ||||
-rw-r--r-- | tools/perf/ui/gtk/hists.c | 11 | ||||
-rw-r--r-- | tools/perf/ui/hist.c | 8 | ||||
-rw-r--r-- | tools/perf/util/config.c | 4 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 59 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 10 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 3 |
18 files changed, 230 insertions, 76 deletions
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index fdfceee0ffd0..fbfa1192923c 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt | |||
@@ -33,17 +33,20 @@ OPTIONS | |||
33 | -d:: | 33 | -d:: |
34 | --dsos=:: | 34 | --dsos=:: |
35 | Only consider symbols in these dsos. CSV that understands | 35 | Only consider symbols in these dsos. CSV that understands |
36 | file://filename entries. | 36 | file://filename entries. This option will affect the percentage |
37 | of the Baseline/Delta column. See --percentage for more info. | ||
37 | 38 | ||
38 | -C:: | 39 | -C:: |
39 | --comms=:: | 40 | --comms=:: |
40 | Only consider symbols in these comms. CSV that understands | 41 | Only consider symbols in these comms. CSV that understands |
41 | file://filename entries. | 42 | file://filename entries. This option will affect the percentage |
43 | of the Baseline/Delta column. See --percentage for more info. | ||
42 | 44 | ||
43 | -S:: | 45 | -S:: |
44 | --symbols=:: | 46 | --symbols=:: |
45 | Only consider these symbols. CSV that understands | 47 | Only consider these symbols. CSV that understands |
46 | file://filename entries. | 48 | file://filename entries. This option will affect the percentage |
49 | of the Baseline/Delta column. See --percentage for more info. | ||
47 | 50 | ||
48 | -s:: | 51 | -s:: |
49 | --sort=:: | 52 | --sort=:: |
@@ -89,6 +92,14 @@ OPTIONS | |||
89 | --order:: | 92 | --order:: |
90 | Specify compute sorting column number. | 93 | Specify compute sorting column number. |
91 | 94 | ||
95 | --percentage:: | ||
96 | Determine how to display the overhead percentage of filtered entries. | ||
97 | Filters can be applied by --comms, --dsos and/or --symbols options. | ||
98 | |||
99 | "relative" means it's relative to filtered entries only so that the | ||
100 | sum of shown entries will be always 100%. "absolute" means it retains | ||
101 | the original value before and after the filter is applied. | ||
102 | |||
92 | COMPARISON | 103 | COMPARISON |
93 | ---------- | 104 | ---------- |
94 | The comparison is governed by the baseline file. The baseline perf.data | 105 | The comparison is governed by the baseline file. The baseline perf.data |
@@ -157,6 +168,10 @@ with: | |||
157 | - period_percent being the % of the hist entry period value within | 168 | - period_percent being the % of the hist entry period value within |
158 | single data file | 169 | single data file |
159 | 170 | ||
171 | - with filtering by -C, -d and/or -S, period_percent might be changed | ||
172 | relative to how entries are filtered. Use --percentage=absolute to | ||
173 | prevent such fluctuation. | ||
174 | |||
160 | ratio | 175 | ratio |
161 | ~~~~~ | 176 | ~~~~~ |
162 | If specified the 'Ratio' column is displayed with value 'r' computed as: | 177 | If specified the 'Ratio' column is displayed with value 'r' computed as: |
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/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 976b00c6cdb1..64ed79c43639 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -123,13 +123,16 @@ Default is to monitor all CPUS. | |||
123 | Show a column with the sum of periods. | 123 | Show a column with the sum of periods. |
124 | 124 | ||
125 | --dsos:: | 125 | --dsos:: |
126 | Only consider symbols in these dsos. | 126 | Only consider symbols in these dsos. This option will affect the |
127 | percentage of the overhead column. See --percentage for more info. | ||
127 | 128 | ||
128 | --comms:: | 129 | --comms:: |
129 | Only consider symbols in these comms. | 130 | Only consider symbols in these comms. This option will affect the |
131 | percentage of the overhead column. See --percentage for more info. | ||
130 | 132 | ||
131 | --symbols:: | 133 | --symbols:: |
132 | Only consider these symbols. | 134 | Only consider these symbols. This option will affect the |
135 | percentage of the overhead column. See --percentage for more info. | ||
133 | 136 | ||
134 | -M:: | 137 | -M:: |
135 | --disassembler-style=:: Set disassembler style for objdump. | 138 | --disassembler-style=:: Set disassembler style for objdump. |
@@ -165,6 +168,15 @@ Default is to monitor all CPUS. | |||
165 | Do not show entries which have an overhead under that percent. | 168 | Do not show entries which have an overhead under that percent. |
166 | (Default: 0). | 169 | (Default: 0). |
167 | 170 | ||
171 | --percentage:: | ||
172 | Determine how to display the overhead percentage of filtered entries. | ||
173 | Filters can be applied by --comms, --dsos and/or --symbols options and | ||
174 | Zoom operations on the TUI (thread, dso, etc). | ||
175 | |||
176 | "relative" means it's relative to filtered entries only so that the | ||
177 | sum of shown entries will be always 100%. "absolute" means it retains | ||
178 | the original value before and after the filter is applied. | ||
179 | |||
168 | INTERACTIVE PROMPTING KEYS | 180 | INTERACTIVE PROMPTING KEYS |
169 | -------------------------- | 181 | -------------------------- |
170 | 182 | ||
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 204fffe22532..6ef80f22c1e2 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -220,7 +220,8 @@ static int setup_compute(const struct option *opt, const char *str, | |||
220 | 220 | ||
221 | static double period_percent(struct hist_entry *he, u64 period) | 221 | static double period_percent(struct hist_entry *he, u64 period) |
222 | { | 222 | { |
223 | u64 total = he->hists->stats.total_period; | 223 | u64 total = hists__total_period(he->hists); |
224 | |||
224 | return (period * 100.0) / total; | 225 | return (period * 100.0) / total; |
225 | } | 226 | } |
226 | 227 | ||
@@ -259,11 +260,18 @@ static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair) | |||
259 | static int formula_delta(struct hist_entry *he, struct hist_entry *pair, | 260 | static int formula_delta(struct hist_entry *he, struct hist_entry *pair, |
260 | char *buf, size_t size) | 261 | char *buf, size_t size) |
261 | { | 262 | { |
263 | u64 he_total = he->hists->stats.total_period; | ||
264 | u64 pair_total = pair->hists->stats.total_period; | ||
265 | |||
266 | if (symbol_conf.filter_relative) { | ||
267 | he_total = he->hists->stats.total_non_filtered_period; | ||
268 | pair_total = pair->hists->stats.total_non_filtered_period; | ||
269 | } | ||
262 | return scnprintf(buf, size, | 270 | return scnprintf(buf, size, |
263 | "(%" PRIu64 " * 100 / %" PRIu64 ") - " | 271 | "(%" PRIu64 " * 100 / %" PRIu64 ") - " |
264 | "(%" PRIu64 " * 100 / %" PRIu64 ")", | 272 | "(%" PRIu64 " * 100 / %" PRIu64 ")", |
265 | pair->stat.period, pair->hists->stats.total_period, | 273 | pair->stat.period, pair_total, |
266 | he->stat.period, he->hists->stats.total_period); | 274 | he->stat.period, he_total); |
267 | } | 275 | } |
268 | 276 | ||
269 | static int formula_ratio(struct hist_entry *he, struct hist_entry *pair, | 277 | static int formula_ratio(struct hist_entry *he, struct hist_entry *pair, |
@@ -327,15 +335,16 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, | |||
327 | return -1; | 335 | return -1; |
328 | } | 336 | } |
329 | 337 | ||
330 | if (al.filtered) | ||
331 | return 0; | ||
332 | |||
333 | if (hists__add_entry(&evsel->hists, &al, sample->period, | 338 | if (hists__add_entry(&evsel->hists, &al, sample->period, |
334 | sample->weight, sample->transaction)) { | 339 | sample->weight, sample->transaction)) { |
335 | pr_warning("problem incrementing symbol period, skipping event\n"); | 340 | pr_warning("problem incrementing symbol period, skipping event\n"); |
336 | return -1; | 341 | return -1; |
337 | } | 342 | } |
338 | 343 | ||
344 | if (al.filtered == 0) { | ||
345 | evsel->hists.stats.total_non_filtered_period += sample->period; | ||
346 | evsel->hists.nr_non_filtered_entries++; | ||
347 | } | ||
339 | evsel->hists.stats.total_period += sample->period; | 348 | evsel->hists.stats.total_period += sample->period; |
340 | return 0; | 349 | return 0; |
341 | } | 350 | } |
@@ -565,7 +574,9 @@ static void hists__compute_resort(struct hists *hists) | |||
565 | next = rb_first(root); | 574 | next = rb_first(root); |
566 | 575 | ||
567 | hists->nr_entries = 0; | 576 | hists->nr_entries = 0; |
577 | hists->nr_non_filtered_entries = 0; | ||
568 | hists->stats.total_period = 0; | 578 | hists->stats.total_period = 0; |
579 | hists->stats.total_non_filtered_period = 0; | ||
569 | hists__reset_col_len(hists); | 580 | hists__reset_col_len(hists); |
570 | 581 | ||
571 | while (next != NULL) { | 582 | while (next != NULL) { |
@@ -732,13 +743,16 @@ static const struct option options[] = { | |||
732 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 743 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", |
733 | "Look for files with symbols relative to this directory"), | 744 | "Look for files with symbols relative to this directory"), |
734 | OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), | 745 | OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), |
746 | OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", | ||
747 | "How to display percentage of filtered entries", parse_filter_percentage), | ||
735 | OPT_END() | 748 | OPT_END() |
736 | }; | 749 | }; |
737 | 750 | ||
738 | static double baseline_percent(struct hist_entry *he) | 751 | static double baseline_percent(struct hist_entry *he) |
739 | { | 752 | { |
740 | struct hists *hists = he->hists; | 753 | u64 total = hists__total_period(he->hists); |
741 | return 100.0 * he->stat.period / hists->stats.total_period; | 754 | |
755 | return 100.0 * he->stat.period / total; | ||
742 | } | 756 | } |
743 | 757 | ||
744 | static int hpp__color_baseline(struct perf_hpp_fmt *fmt, | 758 | static int hpp__color_baseline(struct perf_hpp_fmt *fmt, |
@@ -1120,6 +1134,8 @@ static int data_init(int argc, const char **argv) | |||
1120 | 1134 | ||
1121 | int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) | 1135 | int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) |
1122 | { | 1136 | { |
1137 | perf_config(perf_default_config, NULL); | ||
1138 | |||
1123 | sort_order = diff__default_sort_order; | 1139 | sort_order = diff__default_sort_order; |
1124 | argc = parse_options(argc, argv, options, diff_usage, 0); | 1140 | argc = parse_options(argc, argv, options, diff_usage, 0); |
1125 | 1141 | ||
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 929462aa4943..bd91de07d2a9 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -756,11 +756,13 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
756 | OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), | 756 | OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), |
757 | OPT_END() | 757 | OPT_END() |
758 | }; | 758 | }; |
759 | const char * const kmem_usage[] = { | 759 | const char *const kmem_subcommands[] = { "record", "stat", NULL }; |
760 | "perf kmem [<options>] {record|stat}", | 760 | const char *kmem_usage[] = { |
761 | NULL, | ||
761 | NULL | 762 | NULL |
762 | }; | 763 | }; |
763 | argc = parse_options(argc, argv, kmem_options, kmem_usage, 0); | 764 | argc = parse_options_subcommand(argc, argv, kmem_options, |
765 | kmem_subcommands, kmem_usage, 0); | ||
764 | 766 | ||
765 | if (!argc) | 767 | if (!argc) |
766 | usage_with_options(kmem_usage, kmem_options); | 768 | usage_with_options(kmem_usage, kmem_options); |
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index c852c7a85d32..6148afc995c6 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c | |||
@@ -961,8 +961,10 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) | |||
961 | "perf lock info [<options>]", | 961 | "perf lock info [<options>]", |
962 | NULL | 962 | NULL |
963 | }; | 963 | }; |
964 | const char * const lock_usage[] = { | 964 | const char *const lock_subcommands[] = { "record", "report", "script", |
965 | "perf lock [<options>] {record|report|script|info}", | 965 | "info", NULL }; |
966 | const char *lock_usage[] = { | ||
967 | NULL, | ||
966 | NULL | 968 | NULL |
967 | }; | 969 | }; |
968 | const char * const report_usage[] = { | 970 | const char * const report_usage[] = { |
@@ -976,8 +978,8 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) | |||
976 | for (i = 0; i < LOCKHASH_SIZE; i++) | 978 | for (i = 0; i < LOCKHASH_SIZE; i++) |
977 | INIT_LIST_HEAD(lockhash_table + i); | 979 | INIT_LIST_HEAD(lockhash_table + i); |
978 | 980 | ||
979 | argc = parse_options(argc, argv, lock_options, lock_usage, | 981 | argc = parse_options_subcommand(argc, argv, lock_options, lock_subcommands, |
980 | PARSE_OPT_STOP_AT_NON_OPTION); | 982 | lock_usage, PARSE_OPT_STOP_AT_NON_OPTION); |
981 | if (!argc) | 983 | if (!argc) |
982 | usage_with_options(lock_usage, lock_options); | 984 | usage_with_options(lock_usage, lock_options); |
983 | 985 | ||
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 2e3ade69a58e..4a1a6c94a5eb 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -21,11 +21,6 @@ struct perf_mem { | |||
21 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 21 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
22 | }; | 22 | }; |
23 | 23 | ||
24 | static const char * const mem_usage[] = { | ||
25 | "perf mem [<options>] {record <command> |report}", | ||
26 | NULL | ||
27 | }; | ||
28 | |||
29 | static int __cmd_record(int argc, const char **argv) | 24 | static int __cmd_record(int argc, const char **argv) |
30 | { | 25 | { |
31 | int rec_argc, i = 0, j; | 26 | int rec_argc, i = 0, j; |
@@ -220,9 +215,15 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
220 | " between columns '.' is reserved."), | 215 | " between columns '.' is reserved."), |
221 | OPT_END() | 216 | OPT_END() |
222 | }; | 217 | }; |
218 | const char *const mem_subcommands[] = { "record", "report", NULL }; | ||
219 | const char *mem_usage[] = { | ||
220 | NULL, | ||
221 | NULL | ||
222 | }; | ||
223 | |||
223 | 224 | ||
224 | argc = parse_options(argc, argv, mem_options, mem_usage, | 225 | argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands, |
225 | PARSE_OPT_STOP_AT_NON_OPTION); | 226 | mem_usage, PARSE_OPT_STOP_AT_NON_OPTION); |
226 | 227 | ||
227 | if (!argc || !(strncmp(argv[0], "rec", 3) || mem_operation)) | 228 | if (!argc || !(strncmp(argv[0], "rec", 3) || mem_operation)) |
228 | usage_with_options(mem_usage, mem_options); | 229 | usage_with_options(mem_usage, mem_options); |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c8f21137dfd8..af8cb7a2c9b6 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -123,6 +123,8 @@ static int report__add_mem_hist_entry(struct report *rep, struct addr_location * | |||
123 | 123 | ||
124 | evsel->hists.stats.total_period += cost; | 124 | evsel->hists.stats.total_period += cost; |
125 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); | 125 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
126 | if (!he->filtered) | ||
127 | evsel->hists.stats.nr_non_filtered_samples++; | ||
126 | err = hist_entry__append_callchain(he, sample); | 128 | err = hist_entry__append_callchain(he, sample); |
127 | out: | 129 | out: |
128 | return err; | 130 | return err; |
@@ -176,6 +178,8 @@ static int report__add_branch_hist_entry(struct report *rep, struct addr_locatio | |||
176 | 178 | ||
177 | evsel->hists.stats.total_period += 1; | 179 | evsel->hists.stats.total_period += 1; |
178 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); | 180 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
181 | if (!he->filtered) | ||
182 | evsel->hists.stats.nr_non_filtered_samples++; | ||
179 | } else | 183 | } else |
180 | goto out; | 184 | goto out; |
181 | } | 185 | } |
@@ -209,6 +213,8 @@ static int report__add_hist_entry(struct report *rep, struct perf_evsel *evsel, | |||
209 | err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); | 213 | err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); |
210 | 214 | ||
211 | evsel->hists.stats.total_period += sample->period; | 215 | evsel->hists.stats.total_period += sample->period; |
216 | if (!he->filtered) | ||
217 | evsel->hists.stats.nr_non_filtered_samples++; | ||
212 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); | 218 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
213 | out: | 219 | out: |
214 | return err; | 220 | return err; |
@@ -337,6 +343,11 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report | |||
337 | char buf[512]; | 343 | char buf[512]; |
338 | size_t size = sizeof(buf); | 344 | size_t size = sizeof(buf); |
339 | 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 | |||
340 | if (perf_evsel__is_group_event(evsel)) { | 351 | if (perf_evsel__is_group_event(evsel)) { |
341 | struct perf_evsel *pos; | 352 | struct perf_evsel *pos; |
342 | 353 | ||
@@ -344,8 +355,13 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report | |||
344 | evname = buf; | 355 | evname = buf; |
345 | 356 | ||
346 | for_each_group_member(pos, evsel) { | 357 | for_each_group_member(pos, evsel) { |
347 | nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; | 358 | if (symbol_conf.filter_relative) { |
348 | 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 | } | ||
349 | } | 365 | } |
350 | } | 366 | } |
351 | 367 | ||
@@ -823,6 +839,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
823 | OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), | 839 | OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), |
824 | OPT_CALLBACK(0, "percent-limit", &report, "percent", | 840 | OPT_CALLBACK(0, "percent-limit", &report, "percent", |
825 | "Don't show entries under that percent", parse_percent_limit), | 841 | "Don't show entries under that percent", parse_percent_limit), |
842 | OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", | ||
843 | "how to display percentage of filtered entries", parse_filter_percentage), | ||
826 | OPT_END() | 844 | OPT_END() |
827 | }; | 845 | }; |
828 | struct perf_data_file file = { | 846 | struct perf_data_file file = { |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 9ac0a495c954..d3fb0ed7240a 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1713,8 +1713,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1713 | "perf sched replay [<options>]", | 1713 | "perf sched replay [<options>]", |
1714 | NULL | 1714 | NULL |
1715 | }; | 1715 | }; |
1716 | const char * const sched_usage[] = { | 1716 | const char *const sched_subcommands[] = { "record", "latency", "map", |
1717 | "perf sched [<options>] {record|latency|map|replay|script}", | 1717 | "replay", "script", NULL }; |
1718 | const char *sched_usage[] = { | ||
1719 | NULL, | ||
1718 | NULL | 1720 | NULL |
1719 | }; | 1721 | }; |
1720 | struct trace_sched_handler lat_ops = { | 1722 | struct trace_sched_handler lat_ops = { |
@@ -1736,8 +1738,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1736 | for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++) | 1738 | for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++) |
1737 | sched.curr_pid[i] = -1; | 1739 | sched.curr_pid[i] = -1; |
1738 | 1740 | ||
1739 | argc = parse_options(argc, argv, sched_options, sched_usage, | 1741 | argc = parse_options_subcommand(argc, argv, sched_options, sched_subcommands, |
1740 | PARSE_OPT_STOP_AT_NON_OPTION); | 1742 | sched_usage, PARSE_OPT_STOP_AT_NON_OPTION); |
1741 | if (!argc) | 1743 | if (!argc) |
1742 | usage_with_options(sched_usage, sched_options); | 1744 | usage_with_options(sched_usage, sched_options); |
1743 | 1745 | ||
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 65aaa5bbf7ec..37d30460bada 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -253,6 +253,9 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel, | |||
253 | return NULL; | 253 | return NULL; |
254 | 254 | ||
255 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); | 255 | hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
256 | if (!he->filtered) | ||
257 | evsel->hists.stats.nr_non_filtered_samples++; | ||
258 | |||
256 | return he; | 259 | return he; |
257 | } | 260 | } |
258 | 261 | ||
@@ -694,8 +697,7 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
694 | if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) | 697 | if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) |
695 | top->exact_samples++; | 698 | top->exact_samples++; |
696 | 699 | ||
697 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0 || | 700 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) |
698 | al.filtered) | ||
699 | return; | 701 | return; |
700 | 702 | ||
701 | if (!top->kptr_restrict_warned && | 703 | if (!top->kptr_restrict_warned && |
@@ -1116,6 +1118,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1116 | OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"), | 1118 | OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"), |
1117 | OPT_CALLBACK(0, "percent-limit", &top, "percent", | 1119 | OPT_CALLBACK(0, "percent-limit", &top, "percent", |
1118 | "Don't show entries under that percent", parse_percent_limit), | 1120 | "Don't show entries under that percent", parse_percent_limit), |
1121 | OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", | ||
1122 | "How to display percentage of filtered entries", parse_filter_percentage), | ||
1119 | OPT_END() | 1123 | OPT_END() |
1120 | }; | 1124 | }; |
1121 | const char * const top_usage[] = { | 1125 | const char * const top_usage[] = { |
diff --git a/tools/perf/perf-completion.sh b/tools/perf/perf-completion.sh index ae3a57694b6b..33569847fdcc 100644 --- a/tools/perf/perf-completion.sh +++ b/tools/perf/perf-completion.sh | |||
@@ -121,8 +121,8 @@ __perf_main () | |||
121 | elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then | 121 | elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then |
122 | evts=$($cmd list --raw-dump) | 122 | evts=$($cmd list --raw-dump) |
123 | __perfcomp_colon "$evts" "$cur" | 123 | __perfcomp_colon "$evts" "$cur" |
124 | # List subcommands for 'perf kvm' | 124 | # List subcommands for perf commands |
125 | elif [[ $prev == "kvm" ]]; then | 125 | elif [[ $prev == @(kvm|kmem|mem|lock|sched) ]]; then |
126 | subcmds=$($cmd $prev --list-cmds) | 126 | subcmds=$($cmd $prev --list-cmds) |
127 | __perfcomp_colon "$subcmds" "$cur" | 127 | __perfcomp_colon "$subcmds" "$cur" |
128 | # List long option names | 128 | # List long option names |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 7ec871af3f6f..4d416984c59d 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 | ||
@@ -1370,6 +1389,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1370 | "C Collapse all callchains\n" \ | 1389 | "C Collapse all callchains\n" \ |
1371 | "d Zoom into current DSO\n" \ | 1390 | "d Zoom into current DSO\n" \ |
1372 | "E Expand all callchains\n" \ | 1391 | "E Expand all callchains\n" \ |
1392 | "F Toggle percentage of filtered entries\n" \ | ||
1373 | 1393 | ||
1374 | /* help messages are sorted by lexical order of the hotkey */ | 1394 | /* help messages are sorted by lexical order of the hotkey */ |
1375 | const char report_help[] = HIST_BROWSER_HELP_COMMON | 1395 | const char report_help[] = HIST_BROWSER_HELP_COMMON |
@@ -1475,6 +1495,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1475 | if (env->arch) | 1495 | if (env->arch) |
1476 | tui__header_window(env); | 1496 | tui__header_window(env); |
1477 | continue; | 1497 | continue; |
1498 | case 'F': | ||
1499 | symbol_conf.filter_relative ^= 1; | ||
1500 | continue; | ||
1478 | case K_F1: | 1501 | case K_F1: |
1479 | case 'h': | 1502 | case 'h': |
1480 | case '?': | 1503 | case '?': |
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/config.c b/tools/perf/util/config.c index 3e0fdd369ccb..24519e14ac56 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "util.h" | 11 | #include "util.h" |
12 | #include "cache.h" | 12 | #include "cache.h" |
13 | #include "exec_cmd.h" | 13 | #include "exec_cmd.h" |
14 | #include "util/hist.h" /* perf_hist_config */ | ||
14 | 15 | ||
15 | #define MAXNAME (256) | 16 | #define MAXNAME (256) |
16 | 17 | ||
@@ -355,6 +356,9 @@ int perf_default_config(const char *var, const char *value, | |||
355 | if (!prefixcmp(var, "core.")) | 356 | if (!prefixcmp(var, "core.")) |
356 | return perf_default_core_config(var, value); | 357 | return perf_default_core_config(var, value); |
357 | 358 | ||
359 | if (!prefixcmp(var, "hist.")) | ||
360 | return perf_hist_config(var, value); | ||
361 | |||
358 | /* Add other config variables here. */ | 362 | /* Add other config variables here. */ |
359 | return 0; | 363 | return 0; |
360 | } | 364 | } |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index f38590d7561b..5a892477aa50 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 | ||
329 | static u8 symbol__parent_filter(const struct symbol *parent) | 331 | static 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 = 0; | 679 | hists->nr_non_filtered_entries = 0; |
678 | hists->stats.total_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,12 +697,12 @@ 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; | 700 | ++hists->nr_non_filtered_entries; |
698 | if (h->ms.unfolded) | 701 | if (h->ms.unfolded) |
699 | hists->nr_entries += h->nr_rows; | 702 | hists->nr_non_filtered_entries += h->nr_rows; |
700 | h->row_offset = 0; | 703 | h->row_offset = 0; |
701 | hists->stats.total_period += h->stat.period; | 704 | hists->stats.total_non_filtered_period += h->stat.period; |
702 | hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events; | 705 | hists->stats.nr_non_filtered_samples += h->stat.nr_events; |
703 | 706 | ||
704 | hists__calc_col_len(hists, h); | 707 | hists__calc_col_len(hists, h); |
705 | } | 708 | } |
@@ -721,8 +724,9 @@ void hists__filter_by_dso(struct hists *hists) | |||
721 | { | 724 | { |
722 | struct rb_node *nd; | 725 | struct rb_node *nd; |
723 | 726 | ||
724 | hists->nr_entries = hists->stats.total_period = 0; | 727 | hists->nr_non_filtered_entries = 0; |
725 | hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0; | 728 | hists->stats.total_non_filtered_period = 0; |
729 | hists->stats.nr_non_filtered_samples = 0; | ||
726 | hists__reset_col_len(hists); | 730 | hists__reset_col_len(hists); |
727 | 731 | ||
728 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { | 732 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { |
@@ -754,8 +758,9 @@ void hists__filter_by_thread(struct hists *hists) | |||
754 | { | 758 | { |
755 | struct rb_node *nd; | 759 | struct rb_node *nd; |
756 | 760 | ||
757 | hists->nr_entries = hists->stats.total_period = 0; | 761 | hists->nr_non_filtered_entries = 0; |
758 | hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0; | 762 | hists->stats.total_non_filtered_period = 0; |
763 | hists->stats.nr_non_filtered_samples = 0; | ||
759 | hists__reset_col_len(hists); | 764 | hists__reset_col_len(hists); |
760 | 765 | ||
761 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { | 766 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { |
@@ -785,8 +790,9 @@ void hists__filter_by_symbol(struct hists *hists) | |||
785 | { | 790 | { |
786 | struct rb_node *nd; | 791 | struct rb_node *nd; |
787 | 792 | ||
788 | hists->nr_entries = hists->stats.total_period = 0; | 793 | hists->nr_non_filtered_entries = 0; |
789 | hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0; | 794 | hists->stats.total_non_filtered_period = 0; |
795 | hists->stats.nr_non_filtered_samples = 0; | ||
790 | hists__reset_col_len(hists); | 796 | hists__reset_col_len(hists); |
791 | 797 | ||
792 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { | 798 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { |
@@ -931,3 +937,30 @@ int hists__link(struct hists *leader, struct hists *other) | |||
931 | 937 | ||
932 | return 0; | 938 | return 0; |
933 | } | 939 | } |
940 | |||
941 | u64 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 | } | ||
946 | |||
947 | int parse_filter_percentage(const struct option *opt __maybe_unused, | ||
948 | const char *arg, int unset __maybe_unused) | ||
949 | { | ||
950 | if (!strcmp(arg, "relative")) | ||
951 | symbol_conf.filter_relative = true; | ||
952 | else if (!strcmp(arg, "absolute")) | ||
953 | symbol_conf.filter_relative = false; | ||
954 | else | ||
955 | return -1; | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | int perf_hist_config(const char *var, const char *value) | ||
961 | { | ||
962 | if (!strcmp(var, "hist.percentage")) | ||
963 | return parse_filter_percentage(NULL, value, 0); | ||
964 | |||
965 | return 0; | ||
966 | } | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1f1f513dfe7f..5a0343eb22e2 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -37,9 +37,11 @@ enum hist_filter { | |||
37 | */ | 37 | */ |
38 | struct events_stats { | 38 | struct events_stats { |
39 | u64 total_period; | 39 | u64 total_period; |
40 | u64 total_non_filtered_period; | ||
40 | u64 total_lost; | 41 | u64 total_lost; |
41 | u64 total_invalid_chains; | 42 | u64 total_invalid_chains; |
42 | u32 nr_events[PERF_RECORD_HEADER_MAX]; | 43 | u32 nr_events[PERF_RECORD_HEADER_MAX]; |
44 | u32 nr_non_filtered_samples; | ||
43 | u32 nr_lost_warned; | 45 | u32 nr_lost_warned; |
44 | u32 nr_unknown_events; | 46 | u32 nr_unknown_events; |
45 | u32 nr_invalid_chains; | 47 | u32 nr_invalid_chains; |
@@ -83,6 +85,7 @@ struct hists { | |||
83 | struct rb_root entries; | 85 | struct rb_root entries; |
84 | struct rb_root entries_collapsed; | 86 | struct rb_root entries_collapsed; |
85 | u64 nr_entries; | 87 | u64 nr_entries; |
88 | u64 nr_non_filtered_entries; | ||
86 | const struct thread *thread_filter; | 89 | const struct thread *thread_filter; |
87 | const struct dso *dso_filter; | 90 | const struct dso *dso_filter; |
88 | const char *uid_filter_str; | 91 | const char *uid_filter_str; |
@@ -112,6 +115,7 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); | |||
112 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); | 115 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); |
113 | void hists__output_recalc_col_len(struct hists *hists, int max_rows); | 116 | void hists__output_recalc_col_len(struct hists *hists, int max_rows); |
114 | 117 | ||
118 | u64 hists__total_period(struct hists *hists); | ||
115 | void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); | 119 | void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); |
116 | void hists__inc_nr_events(struct hists *hists, u32 type); | 120 | void hists__inc_nr_events(struct hists *hists, u32 type); |
117 | void events_stats__inc(struct events_stats *stats, u32 type); | 121 | void events_stats__inc(struct events_stats *stats, u32 type); |
@@ -250,4 +254,10 @@ static inline int script_browse(const char *script_opt __maybe_unused) | |||
250 | #endif | 254 | #endif |
251 | 255 | ||
252 | unsigned int hists__sort_list_width(struct hists *hists); | 256 | unsigned int hists__sort_list_width(struct hists *hists); |
257 | |||
258 | struct option; | ||
259 | int parse_filter_percentage(const struct option *opt __maybe_unused, | ||
260 | const char *arg, int unset __maybe_unused); | ||
261 | int perf_hist_config(const char *var, const char *value); | ||
262 | |||
253 | #endif /* __PERF_HIST_H */ | 263 | #endif /* __PERF_HIST_H */ |
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, |