aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-report.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r--tools/perf/builtin-report.c72
1 files changed, 57 insertions, 15 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 287a173523a..d7ff277bdb7 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,6 +33,8 @@
33#include "util/sort.h" 33#include "util/sort.h"
34#include "util/hist.h" 34#include "util/hist.h"
35 35
36#include <linux/bitmap.h>
37
36static char const *input_name = "perf.data"; 38static char const *input_name = "perf.data";
37 39
38static bool force, use_tui, use_stdio; 40static bool force, use_tui, use_stdio;
@@ -45,9 +47,13 @@ static struct perf_read_values show_threads_values;
45static const char default_pretty_printing_style[] = "normal"; 47static const char default_pretty_printing_style[] = "normal";
46static const char *pretty_printing_style = default_pretty_printing_style; 48static const char *pretty_printing_style = default_pretty_printing_style;
47 49
48static char callchain_default_opt[] = "fractal,0.5"; 50static char callchain_default_opt[] = "fractal,0.5,callee";
51static bool inverted_callchain;
49static symbol_filter_t annotate_init; 52static symbol_filter_t annotate_init;
50 53
54static const char *cpu_list;
55static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
56
51static int perf_session__add_hist_entry(struct perf_session *session, 57static int perf_session__add_hist_entry(struct perf_session *session,
52 struct addr_location *al, 58 struct addr_location *al,
53 struct perf_sample *sample, 59 struct perf_sample *sample,
@@ -116,6 +122,9 @@ static int process_sample_event(union perf_event *event,
116 if (al.filtered || (hide_unresolved && al.sym == NULL)) 122 if (al.filtered || (hide_unresolved && al.sym == NULL))
117 return 0; 123 return 0;
118 124
125 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
126 return 0;
127
119 if (al.map != NULL) 128 if (al.map != NULL)
120 al.map->dso->hit = 1; 129 al.map->dso->hit = 1;
121 130
@@ -153,23 +162,22 @@ static int perf_session__setup_sample_type(struct perf_session *self)
153{ 162{
154 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { 163 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
155 if (sort__has_parent) { 164 if (sort__has_parent) {
156 fprintf(stderr, "selected --sort parent, but no" 165 ui__warning("Selected --sort parent, but no "
157 " callchain data. Did you call" 166 "callchain data. Did you call "
158 " perf record without -g?\n"); 167 "'perf record' without -g?\n");
159 return -EINVAL; 168 return -EINVAL;
160 } 169 }
161 if (symbol_conf.use_callchain) { 170 if (symbol_conf.use_callchain) {
162 fprintf(stderr, "selected -g but no callchain data." 171 ui__warning("Selected -g but no callchain data. Did "
163 " Did you call perf record without" 172 "you call 'perf record' without -g?\n");
164 " -g?\n");
165 return -1; 173 return -1;
166 } 174 }
167 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE && 175 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE &&
168 !symbol_conf.use_callchain) { 176 !symbol_conf.use_callchain) {
169 symbol_conf.use_callchain = true; 177 symbol_conf.use_callchain = true;
170 if (callchain_register_param(&callchain_param) < 0) { 178 if (callchain_register_param(&callchain_param) < 0) {
171 fprintf(stderr, "Can't register callchain" 179 ui__warning("Can't register callchain "
172 " params\n"); 180 "params.\n");
173 return -EINVAL; 181 return -EINVAL;
174 } 182 }
175 } 183 }
@@ -262,6 +270,12 @@ static int __cmd_report(void)
262 if (session == NULL) 270 if (session == NULL)
263 return -ENOMEM; 271 return -ENOMEM;
264 272
273 if (cpu_list) {
274 ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
275 if (ret)
276 goto out_delete;
277 }
278
265 if (show_threads) 279 if (show_threads)
266 perf_read_values_init(&show_threads_values); 280 perf_read_values_init(&show_threads_values);
267 281
@@ -386,13 +400,29 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
386 if (!tok) 400 if (!tok)
387 goto setup; 401 goto setup;
388 402
389 tok2 = strtok(NULL, ",");
390 callchain_param.min_percent = strtod(tok, &endptr); 403 callchain_param.min_percent = strtod(tok, &endptr);
391 if (tok == endptr) 404 if (tok == endptr)
392 return -1; 405 return -1;
393 406
394 if (tok2) 407 /* get the print limit */
408 tok2 = strtok(NULL, ",");
409 if (!tok2)
410 goto setup;
411
412 if (tok2[0] != 'c') {
395 callchain_param.print_limit = strtod(tok2, &endptr); 413 callchain_param.print_limit = strtod(tok2, &endptr);
414 tok2 = strtok(NULL, ",");
415 if (!tok2)
416 goto setup;
417 }
418
419 /* get the call chain order */
420 if (!strcmp(tok2, "caller"))
421 callchain_param.order = ORDER_CALLER;
422 else if (!strcmp(tok2, "callee"))
423 callchain_param.order = ORDER_CALLEE;
424 else
425 return -1;
396setup: 426setup:
397 if (callchain_register_param(&callchain_param) < 0) { 427 if (callchain_register_param(&callchain_param) < 0) {
398 fprintf(stderr, "Can't register callchain params\n"); 428 fprintf(stderr, "Can't register callchain params\n");
@@ -436,9 +466,10 @@ static const struct option options[] = {
436 "regex filter to identify parent, see: '--sort parent'"), 466 "regex filter to identify parent, see: '--sort parent'"),
437 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 467 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
438 "Only display entries with parent-match"), 468 "Only display entries with parent-match"),
439 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent", 469 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order",
440 "Display callchains using output_type (graph, flat, fractal, or none) and min percent threshold. " 470 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. "
441 "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt), 471 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
472 OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"),
442 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 473 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
443 "only consider symbols in these dsos"), 474 "only consider symbols in these dsos"),
444 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 475 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
@@ -455,6 +486,7 @@ static const struct option options[] = {
455 "Only display entries resolved to a symbol"), 486 "Only display entries resolved to a symbol"),
456 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 487 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
457 "Look for files with symbols relative to this directory"), 488 "Look for files with symbols relative to this directory"),
489 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
458 OPT_END() 490 OPT_END()
459}; 491};
460 492
@@ -467,6 +499,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
467 else if (use_tui) 499 else if (use_tui)
468 use_browser = 1; 500 use_browser = 1;
469 501
502 if (inverted_callchain)
503 callchain_param.order = ORDER_CALLER;
504
470 if (strcmp(input_name, "-") != 0) 505 if (strcmp(input_name, "-") != 0)
471 setup_browser(true); 506 setup_browser(true);
472 else 507 else
@@ -504,7 +539,14 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
504 if (parent_pattern != default_parent_pattern) { 539 if (parent_pattern != default_parent_pattern) {
505 if (sort_dimension__add("parent") < 0) 540 if (sort_dimension__add("parent") < 0)
506 return -1; 541 return -1;
507 sort_parent.elide = 1; 542
543 /*
544 * Only show the parent fields if we explicitly
545 * sort that way. If we only use parent machinery
546 * for filtering, we don't want it.
547 */
548 if (!strstr(sort_order, "parent"))
549 sort_parent.elide = 1;
508 } else 550 } else
509 symbol_conf.exclude_other = false; 551 symbol_conf.exclude_other = false;
510 552