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.c105
1 files changed, 55 insertions, 50 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index bd0ca81eeaca..3662047cc6b1 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -52,6 +52,7 @@ struct perf_report {
52 symbol_filter_t annotate_init; 52 symbol_filter_t annotate_init;
53 const char *cpu_list; 53 const char *cpu_list;
54 const char *symbol_filter_str; 54 const char *symbol_filter_str;
55 float min_percent;
55 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 56 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
56}; 57};
57 58
@@ -61,6 +62,11 @@ static int perf_report_config(const char *var, const char *value, void *cb)
61 symbol_conf.event_group = perf_config_bool(var, value); 62 symbol_conf.event_group = perf_config_bool(var, value);
62 return 0; 63 return 0;
63 } 64 }
65 if (!strcmp(var, "report.percent-limit")) {
66 struct perf_report *rep = cb;
67 rep->min_percent = strtof(value, NULL);
68 return 0;
69 }
64 70
65 return perf_default_config(var, value, cb); 71 return perf_default_config(var, value, cb);
66} 72}
@@ -187,6 +193,9 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
187 for (i = 0; i < sample->branch_stack->nr; i++) { 193 for (i = 0; i < sample->branch_stack->nr; i++) {
188 if (rep->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym)) 194 if (rep->hide_unresolved && !(bi[i].from.sym && bi[i].to.sym))
189 continue; 195 continue;
196
197 err = -ENOMEM;
198
190 /* 199 /*
191 * The report shows the percentage of total branches captured 200 * The report shows the percentage of total branches captured
192 * and not events sampled. Thus we use a pseudo period of 1. 201 * and not events sampled. Thus we use a pseudo period of 1.
@@ -195,7 +204,6 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
195 &bi[i], 1, 1); 204 &bi[i], 1, 1);
196 if (he) { 205 if (he) {
197 struct annotation *notes; 206 struct annotation *notes;
198 err = -ENOMEM;
199 bx = he->branch_info; 207 bx = he->branch_info;
200 if (bx->from.sym && use_browser == 1 && sort__has_sym) { 208 if (bx->from.sym && use_browser == 1 && sort__has_sym) {
201 notes = symbol__annotation(bx->from.sym); 209 notes = symbol__annotation(bx->from.sym);
@@ -226,11 +234,12 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
226 } 234 }
227 evsel->hists.stats.total_period += 1; 235 evsel->hists.stats.total_period += 1;
228 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 236 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
229 err = 0;
230 } else 237 } else
231 return -ENOMEM; 238 goto out;
232 } 239 }
240 err = 0;
233out: 241out:
242 free(bi);
234 return err; 243 return err;
235} 244}
236 245
@@ -294,6 +303,7 @@ static int process_sample_event(struct perf_tool *tool,
294{ 303{
295 struct perf_report *rep = container_of(tool, struct perf_report, tool); 304 struct perf_report *rep = container_of(tool, struct perf_report, tool);
296 struct addr_location al; 305 struct addr_location al;
306 int ret;
297 307
298 if (perf_event__preprocess_sample(event, machine, &al, sample, 308 if (perf_event__preprocess_sample(event, machine, &al, sample,
299 rep->annotate_init) < 0) { 309 rep->annotate_init) < 0) {
@@ -308,28 +318,25 @@ static int process_sample_event(struct perf_tool *tool,
308 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) 318 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
309 return 0; 319 return 0;
310 320
311 if (sort__branch_mode == 1) { 321 if (sort__mode == SORT_MODE__BRANCH) {
312 if (perf_report__add_branch_hist_entry(tool, &al, sample, 322 ret = perf_report__add_branch_hist_entry(tool, &al, sample,
313 evsel, machine)) { 323 evsel, machine);
324 if (ret < 0)
314 pr_debug("problem adding lbr entry, skipping event\n"); 325 pr_debug("problem adding lbr entry, skipping event\n");
315 return -1;
316 }
317 } else if (rep->mem_mode == 1) { 326 } else if (rep->mem_mode == 1) {
318 if (perf_report__add_mem_hist_entry(tool, &al, sample, 327 ret = perf_report__add_mem_hist_entry(tool, &al, sample,
319 evsel, machine, event)) { 328 evsel, machine, event);
329 if (ret < 0)
320 pr_debug("problem adding mem entry, skipping event\n"); 330 pr_debug("problem adding mem entry, skipping event\n");
321 return -1;
322 }
323 } else { 331 } else {
324 if (al.map != NULL) 332 if (al.map != NULL)
325 al.map->dso->hit = 1; 333 al.map->dso->hit = 1;
326 334
327 if (perf_evsel__add_hist_entry(evsel, &al, sample, machine)) { 335 ret = perf_evsel__add_hist_entry(evsel, &al, sample, machine);
336 if (ret < 0)
328 pr_debug("problem incrementing symbol period, skipping event\n"); 337 pr_debug("problem incrementing symbol period, skipping event\n");
329 return -1;
330 }
331 } 338 }
332 return 0; 339 return ret;
333} 340}
334 341
335static int process_read_event(struct perf_tool *tool, 342static int process_read_event(struct perf_tool *tool,
@@ -384,7 +391,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
384 } 391 }
385 } 392 }
386 393
387 if (sort__branch_mode == 1) { 394 if (sort__mode == SORT_MODE__BRANCH) {
388 if (!self->fd_pipe && 395 if (!self->fd_pipe &&
389 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) { 396 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
390 ui__error("Selected -b but no branch data. " 397 ui__error("Selected -b but no branch data. "
@@ -455,7 +462,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
455 continue; 462 continue;
456 463
457 hists__fprintf_nr_sample_events(rep, hists, evname, stdout); 464 hists__fprintf_nr_sample_events(rep, hists, evname, stdout);
458 hists__fprintf(hists, true, 0, 0, stdout); 465 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
459 fprintf(stdout, "\n\n"); 466 fprintf(stdout, "\n\n");
460 } 467 }
461 468
@@ -574,8 +581,8 @@ static int __cmd_report(struct perf_report *rep)
574 if (use_browser > 0) { 581 if (use_browser > 0) {
575 if (use_browser == 1) { 582 if (use_browser == 1) {
576 ret = perf_evlist__tui_browse_hists(session->evlist, 583 ret = perf_evlist__tui_browse_hists(session->evlist,
577 help, 584 help, NULL,
578 NULL, 585 rep->min_percent,
579 &session->header.env); 586 &session->header.env);
580 /* 587 /*
581 * Usually "ret" is the last pressed key, and we only 588 * Usually "ret" is the last pressed key, and we only
@@ -586,7 +593,7 @@ static int __cmd_report(struct perf_report *rep)
586 593
587 } else if (use_browser == 2) { 594 } else if (use_browser == 2) {
588 perf_evlist__gtk_browse_hists(session->evlist, help, 595 perf_evlist__gtk_browse_hists(session->evlist, help,
589 NULL); 596 NULL, rep->min_percent);
590 } 597 }
591 } else 598 } else
592 perf_evlist__tty_browse_hists(session->evlist, rep, help); 599 perf_evlist__tty_browse_hists(session->evlist, rep, help);
@@ -691,7 +698,19 @@ static int
691parse_branch_mode(const struct option *opt __maybe_unused, 698parse_branch_mode(const struct option *opt __maybe_unused,
692 const char *str __maybe_unused, int unset) 699 const char *str __maybe_unused, int unset)
693{ 700{
694 sort__branch_mode = !unset; 701 int *branch_mode = opt->value;
702
703 *branch_mode = !unset;
704 return 0;
705}
706
707static int
708parse_percent_limit(const struct option *opt, const char *str,
709 int unset __maybe_unused)
710{
711 struct perf_report *rep = opt->value;
712
713 rep->min_percent = strtof(str, NULL);
695 return 0; 714 return 0;
696} 715}
697 716
@@ -700,6 +719,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
700 struct perf_session *session; 719 struct perf_session *session;
701 struct stat st; 720 struct stat st;
702 bool has_br_stack = false; 721 bool has_br_stack = false;
722 int branch_mode = -1;
703 int ret = -1; 723 int ret = -1;
704 char callchain_default_opt[] = "fractal,0.5,callee"; 724 char callchain_default_opt[] = "fractal,0.5,callee";
705 const char * const report_usage[] = { 725 const char * const report_usage[] = {
@@ -796,17 +816,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
796 "Show a column with the sum of periods"), 816 "Show a column with the sum of periods"),
797 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 817 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
798 "Show event group information together"), 818 "Show event group information together"),
799 OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "", 819 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
800 "use branch records for histogram filling", parse_branch_mode), 820 "use branch records for histogram filling", parse_branch_mode),
801 OPT_STRING(0, "objdump", &objdump_path, "path", 821 OPT_STRING(0, "objdump", &objdump_path, "path",
802 "objdump binary to use for disassembly and annotations"), 822 "objdump binary to use for disassembly and annotations"),
803 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 823 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
804 "Disable symbol demangling"), 824 "Disable symbol demangling"),
805 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 825 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
826 OPT_CALLBACK(0, "percent-limit", &report, "percent",
827 "Don't show entries under that percent", parse_percent_limit),
806 OPT_END() 828 OPT_END()
807 }; 829 };
808 830
809 perf_config(perf_report_config, NULL); 831 perf_config(perf_report_config, &report);
810 832
811 argc = parse_options(argc, argv, options, report_usage, 0); 833 argc = parse_options(argc, argv, options, report_usage, 0);
812 834
@@ -846,11 +868,11 @@ repeat:
846 has_br_stack = perf_header__has_feat(&session->header, 868 has_br_stack = perf_header__has_feat(&session->header,
847 HEADER_BRANCH_STACK); 869 HEADER_BRANCH_STACK);
848 870
849 if (sort__branch_mode == -1 && has_br_stack) 871 if (branch_mode == -1 && has_br_stack)
850 sort__branch_mode = 1; 872 sort__mode = SORT_MODE__BRANCH;
851 873
852 /* sort__branch_mode could be 0 if --no-branch-stack */ 874 /* sort__mode could be NORMAL if --no-branch-stack */
853 if (sort__branch_mode == 1) { 875 if (sort__mode == SORT_MODE__BRANCH) {
854 /* 876 /*
855 * if no sort_order is provided, then specify 877 * if no sort_order is provided, then specify
856 * branch-mode specific order 878 * branch-mode specific order
@@ -861,10 +883,12 @@ repeat:
861 883
862 } 884 }
863 if (report.mem_mode) { 885 if (report.mem_mode) {
864 if (sort__branch_mode == 1) { 886 if (sort__mode == SORT_MODE__BRANCH) {
865 fprintf(stderr, "branch and mem mode incompatible\n"); 887 fprintf(stderr, "branch and mem mode incompatible\n");
866 goto error; 888 goto error;
867 } 889 }
890 sort__mode = SORT_MODE__MEMORY;
891
868 /* 892 /*
869 * if no sort_order is provided, then specify 893 * if no sort_order is provided, then specify
870 * branch-mode specific order 894 * branch-mode specific order
@@ -915,8 +939,7 @@ repeat:
915 */ 939 */
916 if (!strstr(sort_order, "parent")) 940 if (!strstr(sort_order, "parent"))
917 sort_parent.elide = 1; 941 sort_parent.elide = 1;
918 } else 942 }
919 symbol_conf.exclude_other = false;
920 943
921 if (argc) { 944 if (argc) {
922 /* 945 /*
@@ -929,25 +952,7 @@ repeat:
929 report.symbol_filter_str = argv[0]; 952 report.symbol_filter_str = argv[0];
930 } 953 }
931 954
932 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); 955 sort__setup_elide(stdout);
933
934 if (sort__branch_mode == 1) {
935 sort_entry__setup_elide(&sort_dso_from, symbol_conf.dso_from_list, "dso_from", stdout);
936 sort_entry__setup_elide(&sort_dso_to, symbol_conf.dso_to_list, "dso_to", stdout);
937 sort_entry__setup_elide(&sort_sym_from, symbol_conf.sym_from_list, "sym_from", stdout);
938 sort_entry__setup_elide(&sort_sym_to, symbol_conf.sym_to_list, "sym_to", stdout);
939 } else {
940 if (report.mem_mode) {
941 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "symbol_daddr", stdout);
942 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso_daddr", stdout);
943 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "mem", stdout);
944 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "local_weight", stdout);
945 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "tlb", stdout);
946 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "snoop", stdout);
947 }
948 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
949 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
950 }
951 956
952 ret = __cmd_report(&report); 957 ret = __cmd_report(&report);
953 if (ret == K_SWITCH_INPUT_DATA) { 958 if (ret == K_SWITCH_INPUT_DATA) {