diff options
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r-- | tools/perf/builtin-report.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 257c9c18cb7e..1532ebde6c4b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -16,6 +16,7 @@ #include <linux/list.h> #include <linux/rbtree.h> #include <linux/err.h> +#include "util/map.h" #include "util/symbol.h" #include "util/callchain.h" #include "util/values.h" @@ -85,6 +86,7 @@ struct report { int socket_filter; DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); struct branch_type_stat brtype_stat; + bool symbol_ipc; }; static int report__config(const char *var, const char *value, void *cb) @@ -129,7 +131,7 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter, struct mem_info *mi; struct branch_info *bi; - if (!ui__has_annotation()) + if (!ui__has_annotation() && !rep->symbol_ipc) return 0; hist__account_cycles(sample->branch_stack, al, sample, @@ -174,7 +176,7 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter, struct perf_evsel *evsel = iter->evsel; int err; - if (!ui__has_annotation()) + if (!ui__has_annotation() && !rep->symbol_ipc) return 0; hist__account_cycles(sample->branch_stack, al, sample, @@ -614,6 +616,21 @@ static int report__collapse_hists(struct report *rep) return ret; } +static int hists__resort_cb(struct hist_entry *he, void *arg) +{ + struct report *rep = arg; + struct symbol *sym = he->ms.sym; + + if (rep->symbol_ipc && sym && !sym->annotate2) { + struct perf_evsel *evsel = hists_to_evsel(he->hists); + + symbol__annotate2(sym, he->ms.map, evsel, + &annotation__default_options, NULL); + } + + return 0; +} + static void report__output_resort(struct report *rep) { struct ui_progress prog; @@ -621,8 +638,10 @@ static void report__output_resort(struct report *rep) ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); - evlist__for_each_entry(rep->session->evlist, pos) - perf_evsel__output_resort(pos, &prog); + evlist__for_each_entry(rep->session->evlist, pos) { + perf_evsel__output_resort_cb(pos, &prog, + hists__resort_cb, rep); + } ui_progress__finish(); } @@ -752,7 +771,8 @@ static int tasks_print(struct report *rep, FILE *fp) for (i = 0; i < THREADS__TABLE_SIZE; i++) { struct threads *threads = &machine->threads[i]; - for (nd = rb_first(&threads->entries); nd; nd = rb_next(nd)) { + for (nd = rb_first_cached(&threads->entries); nd; + nd = rb_next(nd)) { task = tasks + itask++; task->thread = rb_entry(nd, struct thread, rb_node); @@ -879,7 +899,7 @@ static int __cmd_report(struct report *rep) rep->nr_entries += evsel__hists(pos)->nr_entries; if (rep->nr_entries == 0) { - ui__error("The %s file has no samples!\n", data->file.path); + ui__error("The %s data has no samples!\n", data->path); return 0; } @@ -955,9 +975,9 @@ int cmd_report(int argc, const char **argv) int branch_mode = -1; bool branch_call_mode = false; #define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent" - const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n" - CALLCHAIN_REPORT_HELP - "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT; + static const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n" + CALLCHAIN_REPORT_HELP + "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT; char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; const char * const report_usage[] = { "perf report [<options>]", @@ -1133,6 +1153,7 @@ int cmd_report(int argc, const char **argv) .mode = PERF_DATA_MODE_READ, }; int ret = hists__init(); + char sort_tmp[128]; if (ret < 0) return ret; @@ -1186,8 +1207,8 @@ int cmd_report(int argc, const char **argv) input_name = "perf.data"; } - data.file.path = input_name; - data.force = symbol_conf.force; + data.path = input_name; + data.force = symbol_conf.force; repeat: session = perf_session__new(&data, false, &report.tool); @@ -1284,6 +1305,24 @@ repeat: else use_browser = 0; + if (sort_order && strstr(sort_order, "ipc")) { + parse_options_usage(report_usage, options, "s", 1); + goto error; + } + + if (sort_order && strstr(sort_order, "symbol")) { + if (sort__mode == SORT_MODE__BRANCH) { + snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s", + sort_order, "ipc_lbr"); + report.symbol_ipc = true; + } else { + snprintf(sort_tmp, sizeof(sort_tmp), "%s,%s", + sort_order, "ipc_null"); + } + + sort_order = sort_tmp; + } + if (setup_sorting(session->evlist) < 0) { if (sort_order) parse_options_usage(report_usage, options, "s", 1); @@ -1311,7 +1350,7 @@ repeat: * so don't allocate extra space that won't be used in the stdio * implementation. */ - if (ui__has_annotation()) { + if (ui__has_annotation() || report.symbol_ipc) { ret = symbol__annotation_init(); if (ret < 0) goto error; |