diff options
Diffstat (limited to 'tools/perf/builtin-report.c')
| -rw-r--r-- | tools/perf/builtin-report.c | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 287a173523a..f854efda768 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 | |||
| 36 | static char const *input_name = "perf.data"; | 38 | static char const *input_name = "perf.data"; |
| 37 | 39 | ||
| 38 | static bool force, use_tui, use_stdio; | 40 | static bool force, use_tui, use_stdio; |
| @@ -45,9 +47,13 @@ static struct perf_read_values show_threads_values; | |||
| 45 | static const char default_pretty_printing_style[] = "normal"; | 47 | static const char default_pretty_printing_style[] = "normal"; |
| 46 | static const char *pretty_printing_style = default_pretty_printing_style; | 48 | static const char *pretty_printing_style = default_pretty_printing_style; |
| 47 | 49 | ||
| 48 | static char callchain_default_opt[] = "fractal,0.5"; | 50 | static char callchain_default_opt[] = "fractal,0.5,callee"; |
| 51 | static bool inverted_callchain; | ||
| 49 | static symbol_filter_t annotate_init; | 52 | static symbol_filter_t annotate_init; |
| 50 | 53 | ||
| 54 | static const char *cpu_list; | ||
| 55 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | ||
| 56 | |||
| 51 | static int perf_session__add_hist_entry(struct perf_session *session, | 57 | static 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 | ||
| @@ -262,6 +271,12 @@ static int __cmd_report(void) | |||
| 262 | if (session == NULL) | 271 | if (session == NULL) |
| 263 | return -ENOMEM; | 272 | return -ENOMEM; |
| 264 | 273 | ||
| 274 | if (cpu_list) { | ||
| 275 | ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); | ||
| 276 | if (ret) | ||
| 277 | goto out_delete; | ||
| 278 | } | ||
| 279 | |||
| 265 | if (show_threads) | 280 | if (show_threads) |
| 266 | perf_read_values_init(&show_threads_values); | 281 | perf_read_values_init(&show_threads_values); |
| 267 | 282 | ||
| @@ -386,13 +401,29 @@ parse_callchain_opt(const struct option *opt __used, const char *arg, | |||
| 386 | if (!tok) | 401 | if (!tok) |
| 387 | goto setup; | 402 | goto setup; |
| 388 | 403 | ||
| 389 | tok2 = strtok(NULL, ","); | ||
| 390 | callchain_param.min_percent = strtod(tok, &endptr); | 404 | callchain_param.min_percent = strtod(tok, &endptr); |
| 391 | if (tok == endptr) | 405 | if (tok == endptr) |
| 392 | return -1; | 406 | return -1; |
| 393 | 407 | ||
| 394 | if (tok2) | 408 | /* get the print limit */ |
| 409 | tok2 = strtok(NULL, ","); | ||
| 410 | if (!tok2) | ||
| 411 | goto setup; | ||
| 412 | |||
| 413 | if (tok2[0] != 'c') { | ||
| 395 | callchain_param.print_limit = strtod(tok2, &endptr); | 414 | callchain_param.print_limit = strtod(tok2, &endptr); |
| 415 | tok2 = strtok(NULL, ","); | ||
| 416 | if (!tok2) | ||
| 417 | goto setup; | ||
| 418 | } | ||
| 419 | |||
| 420 | /* get the call chain order */ | ||
| 421 | if (!strcmp(tok2, "caller")) | ||
| 422 | callchain_param.order = ORDER_CALLER; | ||
| 423 | else if (!strcmp(tok2, "callee")) | ||
| 424 | callchain_param.order = ORDER_CALLEE; | ||
| 425 | else | ||
| 426 | return -1; | ||
| 396 | setup: | 427 | setup: |
| 397 | if (callchain_register_param(&callchain_param) < 0) { | 428 | if (callchain_register_param(&callchain_param) < 0) { |
| 398 | fprintf(stderr, "Can't register callchain params\n"); | 429 | fprintf(stderr, "Can't register callchain params\n"); |
| @@ -436,9 +467,10 @@ static const struct option options[] = { | |||
| 436 | "regex filter to identify parent, see: '--sort parent'"), | 467 | "regex filter to identify parent, see: '--sort parent'"), |
| 437 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, | 468 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, |
| 438 | "Only display entries with parent-match"), | 469 | "Only display entries with parent-match"), |
| 439 | OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent", | 470 | 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. " | 471 | "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), | 472 | "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), |
| 473 | OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"), | ||
| 442 | OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", | 474 | OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", |
| 443 | "only consider symbols in these dsos"), | 475 | "only consider symbols in these dsos"), |
| 444 | OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", | 476 | OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", |
| @@ -455,6 +487,7 @@ static const struct option options[] = { | |||
| 455 | "Only display entries resolved to a symbol"), | 487 | "Only display entries resolved to a symbol"), |
| 456 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", | 488 | OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", |
| 457 | "Look for files with symbols relative to this directory"), | 489 | "Look for files with symbols relative to this directory"), |
| 490 | OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), | ||
| 458 | OPT_END() | 491 | OPT_END() |
| 459 | }; | 492 | }; |
| 460 | 493 | ||
| @@ -467,6 +500,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) | |||
| 467 | else if (use_tui) | 500 | else if (use_tui) |
| 468 | use_browser = 1; | 501 | use_browser = 1; |
| 469 | 502 | ||
| 503 | if (inverted_callchain) | ||
| 504 | callchain_param.order = ORDER_CALLER; | ||
| 505 | |||
| 470 | if (strcmp(input_name, "-") != 0) | 506 | if (strcmp(input_name, "-") != 0) |
| 471 | setup_browser(true); | 507 | setup_browser(true); |
| 472 | else | 508 | else |
| @@ -504,7 +540,14 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) | |||
| 504 | if (parent_pattern != default_parent_pattern) { | 540 | if (parent_pattern != default_parent_pattern) { |
| 505 | if (sort_dimension__add("parent") < 0) | 541 | if (sort_dimension__add("parent") < 0) |
| 506 | return -1; | 542 | return -1; |
| 507 | sort_parent.elide = 1; | 543 | |
| 544 | /* | ||
| 545 | * Only show the parent fields if we explicitly | ||
| 546 | * sort that way. If we only use parent machinery | ||
| 547 | * for filtering, we don't want it. | ||
| 548 | */ | ||
| 549 | if (!strstr(sort_order, "parent")) | ||
| 550 | sort_parent.elide = 1; | ||
| 508 | } else | 551 | } else |
| 509 | symbol_conf.exclude_other = false; | 552 | symbol_conf.exclude_other = false; |
| 510 | 553 | ||
